对于android-音板应用程序上的Mediaplayer错误感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解media.audioplayer.musicplayer,并且为您提供关于An
对于android-音板应用程序上的Mediaplayer错误感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解media.audioplayer.musicplayer,并且为您提供关于Android 5.0(Lollipop)中的MediaPlayer抛出错误、Android Media Player保留应用程序实例并导致内存泄漏、Android Media Player错误(100,0)、Android MediaPlayer的宝贵知识。
本文目录一览:- android-音板应用程序上的Mediaplayer错误(media.audioplayer.musicplayer)
- Android 5.0(Lollipop)中的MediaPlayer抛出错误
- Android Media Player保留应用程序实例并导致内存泄漏
- Android Media Player错误(100,0)
- Android MediaPlayer
android-音板应用程序上的Mediaplayer错误(media.audioplayer.musicplayer)
我有一个音板应用程序,可以在按下音频文件的按钮时调用该文件.但是,在大多数按钮被按下并播放之后,我开始出现这些Mediaplayer错误.有谁知道如何检测它,然后重新启动或完全阻止它发生?谢谢你的时间.
-colby
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
ImageButton button = (ImageButton) findViewById(entry.getKey());
button.setonClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
int sound = map.get(v.getId());
mp = MediaPlayer.create(myMain.this, sound);
mp.prepare();
} catch (IllegalStateException e) {
} catch (IOException e) {
}
mp.seekTo(0);
mp.start();
}
}
);
}
04-13 10:11:39.873:INFO / MediaPlayer(23152):MediaPlayer start()
04-13 10:11:39.873:VERBOSE / MediaPlayerService(18229):[666] setLooping(0)
04-13 13:11:39.873:VERBOSE / MediaPlayerService(18229):[666] setVolume(1.000000,1.000000)
04-13 10:11:39.873:VERBOSE / AudioSink(18229):setVolume(1.000000,1.000000)
04-13 13:11:39.873:VERBOSE / MediaPlayerService(18229):[666]开始
04-13 13:11:39.873:DEBUG / AwesomePlayer(18229):[U5B]播放(556)
04-13 10:11:39.873:DEBUG / AwesomePlayer(18229):[U5B] play_l(562)
04-13 10:11:39.873:VERBOSE / AudioSink(18229):打开(44100,1,1,4)
04-13 10:11:39.873:错误/ audioflinger(18229):没有更多可用的曲目名称
04-13 10:11:39.873:错误/ AudioTrack(18229):audioflinger无法创建轨道,状态:12
04-13 10:11:39.873:错误/ AudioSink(18229):无法创建音轨
04-13 10:11:39.873:错误/ MediaPlayer(23152):错误(-19,0)
04-13 10:11:39.894:INFO / MediaPlayer(23152):MediaPlayer handleMessage what = 5
04-13 10:11:39.894:INFO / MediaPlayer(23152):MediaPlayer handleMessage什么= 1
04-13 10:11:39.894:INFO / MediaPlayer(23152):MediaPlayer handleMessage what = 4
04-13 10:11:42.114:INFO / MediaPlayer(23152):MediaPlayer create()
04-13 10:11:42.114:INFO / MediaPlayer(23152):MediaPlayer
04-13 10:11:42.114:VERBOSE / MediaPlayerService(18229):客户端(667)构造函数
解决方法:
詹姆斯有正确的主意.过一会儿,您创建了太多的MediaPlayer实例,并且内存不足.我之前发布的解决方案可以达到这种效果:
public MediaPlayer mp;
public Resources res = getResources();
View.OnClickListener listener = new View.OnClickListener() {
public void onClick(View v) {
try {
int sound = map.get(v.getId());
AssetFileDescriptor afd = res.openRawResourceFd(sound);
mp.reset();
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
mp.start();
} catch (IOException e) {
e.printstacktrace();
}
}
}
for(Map.Entry<Integer, Integer> entry : map.entrySet()) {
ImageButton button = (ImageButton)findViewById(entry.getKey());
button.setonClickListener(listener);
}
这可能不会编译(我假设您的声音ID来自res / raw文件夹),但是想法是,只有一个MediaPlayer实例,并且每当单击按钮时,都重置该实例,将数据源设置为相应的FileDescriptor,准备它,然后开始播放.
Android 5.0(Lollipop)中的MediaPlayer抛出错误
我编写了一个媒体应用程序,该应用程序使用HTTP连接流式传输MP3.这在Android版本2.x-4.x上一直很好用,但现在在5.x中产生错误.该应用程序循环播放包含MP3的播放列表对象,每个对象都有其自己的唯一HTTP地址.第一个文件流很好,但是在调用prepareAsync()时,下一个文件(与哪个文件无关)会产生以下错误:
07-04 18:57:19.785 65-10860/? E/NuCachedSource2﹕ source returned error -1, 10 retries left
07-04 18:57:22.874 65-10860/? E/NuCachedSource2﹕ source returned error -1, 9 retries left
07-04 18:57:25.907 65-10860/? E/NuCachedSource2﹕ source returned error -1, 8 retries left
07-04 18:57:28.929 65-10860/? E/NuCachedSource2﹕ source returned error -1, 7 retries left
07-04 18:57:31.972 65-10860/? E/NuCachedSource2﹕ source returned error -1, 6 retries left
07-04 18:57:35.024 65-10860/? E/NuCachedSource2﹕ source returned error -1, 5 retries left
07-04 18:57:38.062 65-10860/? E/NuCachedSource2﹕ source returned error -1, 4 retries left
07-04 18:57:41.085 65-10860/? E/NuCachedSource2﹕ source returned error -1, 3 retries left
07-04 18:57:44.110 65-10860/? E/NuCachedSource2﹕ source returned error -1, 2 retries left
07-04 18:57:47.262 65-10860/? E/NuCachedSource2﹕ source returned error -1, 1 retries left
07-04 18:57:50.294 65-10860/? E/NuCachedSource2﹕ source returned error -1, 0 retries left
07-04 18:57:50.419 65-10857/? E/GenericSource﹕ Failed to init from data source!
07-04 18:57:50.428 9592-9758/net.kicksass.shootingstarbbs.streamstar E/MediaPlayer﹕ error (1, -2147483648)
07-04 18:57:50.429 9592-9592/net.kicksass.shootingstarbbs.streamstar E/MediaPlayer﹕ Error (1,-2147483648)
通常,应用程序先调用MediaPlayer的setDataSource(url),再调用prepareAsync(),然后等待onPreparedListener触发,然后再调用start()开始流式传输.流完成后,它将调用reset(),然后再调用setDataSource(url),在此过程再次开始.
为什么棒棒糖的MediaPlayer抛出此错误?
解决方法:
看起来像setDataSource(string)方法,该方法用于使用Android的早期版本自动编码传入的URL,但不再在v5.x中使用.发生错误是因为Web服务器返回HTTP 404 Not Found.当我在将URL传递给setDataSource()之前对URL进行编码时,它可以工作.
更令人困惑的是,我的应用对URL的编码不一致,因此有时它可以工作,而有时却没有.
Android Media Player保留应用程序实例并导致内存泄漏
我有一个媒体播放器作为成员变量的活动.
我的媒体播放器初始化如下:
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(MyActivity.this, URL);
mMediaPlayer.prepareAsync();
//i set a on Prepared Listener to start playing on Prepared
一切正常,然后我覆盖我的活动onStop方法以发布Media Player.
if(mMediaPlayer!=null){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
mMediaPlayer.release();
mMediaPlayer=null;
}
但是在活动停止后,我从LeakCanary收到了内存泄漏报告.
该报告是这样的:
MyApp.Instance->
MyApp.mloadedApk->
LoadedApk.mReceivers->
ArrayMap.mArray->
arrayObject[].[3]->
ArrayMap.mArray->
arrayObject[][0]->
MediaPlayer.mProxyReceiver->
MediaPlayer.mProxyContext->
leaks MyActivity instance.
MyApp.Instance->
MyApp.mloadedApk->
LoadedApk.mReceivers->
ArrayMap.mArray->
arrayObject[].[3]->
ArrayMap.mArray->
arrayObject[][0]->
MediaPlayer.mProxyReceiver->
MediaPlayer.mProxyContext->
leaks MyActivity instance.
是的,我有一个扩展应用程序的MyApp类,并且在静态字段中持有对MyApp实例的引用,但是我从未在活动中使用该引用,如何解决此泄漏?
[编辑]
这是我的活动代码:
public class PlayActivity extends ActionBaractivity {
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
getSupportActionBar().setdisplayHomeAsUpEnabled(true);
}
@Override
protected void onStop() {
super.onStop();
if(mediaPlayer!=null){
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer=null;
}
}
public void playIt(View view){
if(mediaPlayer==null){
mediaPlayer = new MediaPlayer();
mediaPlayer.setonPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}
if(!mediaPlayer.isPlaying()){
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(PlayActivity.this, Uri.parse("http://www.noiseaddicts.com/samples_1w72b820/142.mp3"));
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printstacktrace();
}
}
}
}
解决方法:
在测试期间,我发现这是在HTTP流传输期间发生的.
当我检查目标上的MediaPlayer的源代码(在我的示例中为API19)时,确实存在一个StreamProxy实例正在设置和分配,但没有在release方法中释放,而仅在reset方法中释放.
这为我工作:
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
Android Media Player错误(100,0)
错误指定:
const PVMFStatus PVMFInfoLast = 100; ” Placeholder for end of range”
但我无法处理这个错误,谢谢你的帮助.
解决方法
在类体内写
video_view.setonErrorListener(this);
然后使用此方法覆盖方法OnError(MediaPlayer mp,int what,int extra)
@Override public boolean onError(MediaPlayer mp,int extra) { if (what == 100) { video_view.stopPlayback(); Intent inn = new Intent(HelloInterruptVideoStream.this,TabAct.class); startActivity(inn); } else if (what == 1) { pb2.setVisibility(View.GONE); Log.i("My Error ","handled here"); video_view.stopPlayback(); Intent inn = new Intent(HelloInterruptVideoStream.this,TabAct.class); startActivity(inn); } else if(what == 800) { video_view.stopPlayback(); Intent inn = new Intent(HelloInterruptVideoStream.this,TabAct.class); startActivity(inn); } else if (what == 701) { video_view.stopPlayback(); Intent inn = new Intent(HelloInterruptVideoStream.this,TabAct.class); startActivity(inn); } else if(what == 700) { video_view.stopPlayback(); Toast.makeText(getApplicationContext(),"Bad Media format ",Toast.LENGTH_SHORT).show(); Intent inn = new Intent(HelloInterruptVideoStream.this,TabAct.class); startActivity(inn); } else if (what == -38) { video_view.stopPlayback(); Intent inn = new Intent(HelloInterruptVideoStream.this,TabAct.class); startActivity(inn); } return false; }
Android MediaPlayer
MediaPlayer
这个类主要是播放视频类.
AudioManager
这个类管理在一个设备上的音频资源和音频输出流.
Manifest 声明
1. 网络声明
<uses-permission android:name="android.permission.INTERNET" />
2. 如果播放器应用需要将屏幕变暗或者停止处理器 , 或者需要调用 MediaPlayer.setScreenOnWhilePlaying() 或者 MediaPlayer.setWakeMode() 方法,需要声明:
<uses-permission android:name="android.permission.WAKE_LOCK" />
MediaPlayer 类的使用
MediaPlayer 类支持几种不同媒体来源例如:
1. 本地资源
2. 网络 URI
3. 外部 URL(流)
媒体来源 1: 本地资源 (存储在应该的 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" 资源是不需要系统做任何解析的一个文件. 然而 , 这个资源不应该是原始音频文件. 它应该是一个被支持的正确编码和格式化的媒体文件.
媒体来源 2: 网络 URI
Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();
媒体来源 3: 通过 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();
注意: 在调用 setDataSource(), 方法的时候一定要 catch 获得 抛出 IllegalArgumentException 和 IOException 两个异常 , 因为你定义的文件可能不存在.
Asynchronous Preparation 异步准备
原则上可以直接使用 MediaPlayer. 但是 , 有一些事情必须要一体化. 例如 , 调用 prepare() 方法可能花费很长时间来执行,因为它可能涉及到抓取或者编码媒体数据. 因此 , 这中情况下任何方法都有可能花费很长时间去执行 , 你不应该在 UI 线程中调用这个方法.
框架支持的一个很方便完成这个操作的方法是: 调用 prepareAsync() 方法. 这个方法在后台开始 prepare 媒体并且马上就返回. 当 media 准备完成. 通过设置 setOnPreparedListener() 的 MediaPlayer.OnPreparedListener 接口中 onPrepared() 方法就会被调用.
Managing State(状态管理)
MediaPlayer 有一个内部状态当你写你的代码时你必须时刻注意,因为某些操作只有在特定的状态下才有效.
具体状态请查看 SDK 文档中 MediaPlayer 类.
Releasing the MediaPlayer(释放 MediaPlayer)
一个 MediaPlayer 可能会消耗大量的系统资源. 因此 , 你应该总是采取额外的方式去确保你不会持有一个 MediaPlayer 实例,超过实际需要.
当你完成操作时时 , 你应该总是调用 release() 方法去确保任何分配的系统资源给正确的释放掉. 例如 , 当你使用一个 MediaPlayer 而你的 activity 调用 onStop() 方法时 , 你一定要释放 MediaPlayer . 因为当你的 activity 没有和用户交互的时候 , 去持有一个 MediaPlayer 意义不大.(除非需要在后台播放媒体文件).
当你的 activity 是 resumed 或者 restarted 状态,你需要去创建一个新的 MediaPlayer 并且准备再次回复之前的播放.
这里是释放和让 MediaPlayer 为 null 的代码:
mediaPlayer.release();
mediaPlayer = null;
Using a Service with MediaPlayer
Running asynchronously(异步运行)
首先 , 像一个 activity 一样 , 在一个 Service 中的所有工作默认的是在一个单独的线程中 , 如果你在同一个应用中运行一个 activity 和一个 Service, 默认的他们使用的是同一个线程 (主线程). 因此 ,service 需要快速处理引入的 intent 并且在处理这些 intent 的时候不要处理冗长的运算.
如果需要这么做 , 你一定要异步处理这些事情.
举例来说 , 当在你的主线程中使用一个 MediaPlayer 时. 你应该调用 prepareAsync() 而不是 prepare() , 例如:
public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final 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 here
mMediaPlayer.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(异常异步处理)
public class MyService extends Service implements MediaPlayer.OnErrorListener {
MediaPlayer mMediaPlayer;
public void initMediaPlayer() {
// ...initialize the MediaPlayer here...
mMediaPlayer.setOnErrorListener(this);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
}
}
这个是很重要的 , 当一个错误出现 , MediaPlayer 移动到到 Error 状态并且在你再次使用它之前你一定要重置 MediaPlayer.
Using wake locks
当设计应用在后台播放媒体文件时 , 设备在你的 service 运行的时候可能会待机. 因为 android 系统在设备待机的时候尝试节省电池. 所有系统会尝试切断任何非必要的手机特征 , 包括 CPU 和 Wifi 硬件. 然而 , 如果你的 service 正在播放或者流处理音乐 , 你会想防止系统干扰你的播放.
为了确保你的 service 继续运行在这些条件下 , 你需要使用 "wake locks". 一个 wake lock 是一种提醒体统你的应用正在使用一些特性,系统应该保持可用 , 就算电话处于空闲状态.
注意: 你应该总是节俭的使用 wake locks, 并且持有他们只有在真正必要的时候 , 因为他们会大大降低设备电池寿命.
要确保 CPU 在你的 MediaPlayer 播放的时候继续处于运行状态,当初始化你的 MediaPlayer 时调用 setWakeMode() . 一旦你这么做了 , MediaPlayer 会持有指定的 lock 在播放的时候. 并且在 paused 或者 stoped 状态时 , 会释放掉这个 lock.
mMediaPlayer = new MediaPlayer();
// ... other initialization here ...
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
在这个例子中获得 wake lock 的前提是只有当 CPU 处于清醒状态. 如果你是通过网络流媒体并且使用的是 wifi 的话 , 你可以也想要去持有一个 WifiLock , 这种方式你必须收到获取和释放. 因此 , 当你开始通过远程 URL 准备 MediaPlayer 时,你应该创建和获得 Wi-Fi lock . 例如:
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
当你暂停或者停止媒体 , 或者你很长时间没有用到网络 , 你应该释放这个 lock:
wifiLock.release();
Handling audio focus(处理音频的焦点)
尽管只有一个 activity 可以运行在任何时候 , 但是 android 是一个多任务环境. 这给使用音频的应用产生了一个特别的挑战 , 因为哪里只有一个音频输入但是可能有几个媒体 service 竞争使用. 在 android2.2 之前 , 没有一个内置机制来解决这个问题. 这可能在某些情况下导致糟糕的用户体验.
当你的应用需要输入音频时 , 你应该总是请求音频聚焦 (audio focus). 一旦它有了 , 它可以使用自由的输出声音了 , 但是它应该总是保持对焦点的监听. 如果它被通知它已经失去了音频焦点 , 它应该马上杀掉这个音频或者降低它到一个安静的水平并且只有当它再次接受到 focus 时再重新播放.
要请求音频聚焦 , 你一定要调用 AudioManager 的 requestAudioFocus() 方法,
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// could not get audio focus.
}
requestAudioFocus() 方法的第一个参数是一个 AudioManager.OnAudioFocusChangeListener , 当一个音频焦点发生改变的时候他的 onAudioFocusChange() 方法会被调用.
因此你可以在 activity 或者 service 中实现这个接口:
class MyService extends Service
implements AudioManager.OnAudioFocusChangeListener {
// ....
public void onAudioFocusChange(int focusChange) {
// Do something based on focus change...
}
}
focusChange 参数告诉你音频焦点发生了什么样的改变:
· AUDIOFOCUS_GAIN: 你得到这个音频的焦点
· AUDIOFOCUS_LOSS: 你可能长时间失去了这个音频的焦点. 你一定要停止所有的音频播放. 因为你应该希望不要在后台聚焦太长事件 , 这个是一个好地方去尽可能的释放掉你的资源. 例如: 你应该释放掉 MediaPlayer.
· AUDIOFOCUS_LOSS_TRANSIENT: 你暂时的失去了音频的焦点 , 但是应该要马上回到焦点上. 你一定要停止掉所有的音频的播放 , 但是你能持有你的资源因为你可能很快的再次获得聚焦.
· AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: 你暂时的失去了音频的焦点 , 但是你允许继续用小音量播放音乐而不是完全杀掉音频.
使用代码:
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
// resume playback
if (mMediaPlayer == null) initMediaPlayer();
else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
mMediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
// Lost focus for an unbounded amount of time: stop playback and release media player
if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// Lost focus for a short time, but we have to stop
// playback. We don''t release the media player because playback
// is likely to resume
if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but it''s ok to keep playing
// at an attenuated level
if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
记住这些 api 只有在 API 等级为 8(android 2.2) 或者之上才能用.
Handling the AUDIO_BECOMING_NOISY Intent
有可能会出现噪音的情况 , 例如 , 用户先用耳机听音乐 , 然后把耳机给拔出来的这种情况.
你可以通过处理 ACTION_AUDIO_BECOMING_NOISY 意图来确保在这种情况下,你的应用停止播放音乐.
<receiver android:name=".MusicIntentReceiver">
<intent-filter>
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
public class MusicIntentReceiver implements android.content.BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals(
android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
// signal your service to stop playback
// (via an Intent, for instance)
}
}
}
文章链接:http://blog.csdn.net/murongshusheng/article/details/7580689
今天关于android-音板应用程序上的Mediaplayer错误和media.audioplayer.musicplayer的介绍到此结束,谢谢您的阅读,有关Android 5.0(Lollipop)中的MediaPlayer抛出错误、Android Media Player保留应用程序实例并导致内存泄漏、Android Media Player错误(100,0)、Android MediaPlayer等更多相关知识的信息可以在本站进行查询。
本文标签: