Android MediaPlayer在API 21上失败(但不是API 19或22!)

时间:2018-05-15 11:23:27

标签: android audio crash buffer android-mediaplayer

在我的应用中,我想有一个简单的方法,使用MediaPlayer类播放一次声音资源(如果需要,再次播放)。

我已经成功实现了这一点(请参阅下面的代码),并在使用API​​ 23的真实硬件设备上成功测试了它,并且还在API级别从19一直到P ...的仿真器上进行了测试... EXCEPT FOR API 21 ,哪里失败。

难道不奇怪吗?为什么某些东西可以在API 19 ...和23上运行,但不是21?

那么失败是什么意思?那么,在API 21上,如果按播放按钮,没有声音播放,似乎没有任何事情发生(尽管如果你偷看logcat,你应该看到所有方式可怕的本土图书馆信息,包括许多"死亡"甚至"墓碑"或两个)。

如果你继续第二次按 play ,会发生同样的事情,在logcat中生成更多的内部错误消息......第三次,你最终会崩溃。

我能看到的唯一错误可能与我控制的任何内容有关,就是在Log.i中捕获的异常:

  

" com.example.boober.stackqmediaplayer I / SFX:   错误:java.io.IOException:准备失败:status = 0x64"

所有其他消息和最终堆栈跟踪都由内部本机库生成。

我已经搜索了这些错误,请阅读logcat和MediaPlayer文档。希望我只是做一些根本愚蠢的事情,有人可以指出我。

我真的希望也许有人可以看看。

我已经完成了一个非常简单的问题示例,该问题应该很容易在Android Studio中剪切/粘贴/重建,以便您可以重现问题:

MainActivity:

public class MainActivity extends Activity {

    MediaPlayer ourPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ourPlayer = MediaPlayer.create(this, R.raw.soundeffect);
    }

    public void play(View v) {
        try {
            ourPlayer.stop();
            ourPlayer.prepare();
            ourPlayer.start();
        } catch (IOException e) {
            Log.i("SFX", "error:" + e.toString());
        }
    }
}

activity_main.xml中:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:onClick="play"
        android:clickable="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="PLAY"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Res文件夹(使用任何音频文件):

enter image description here

的build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.example.boober.stackqmediaplayer"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

2 个答案:

答案 0 :(得分:1)

根据MediaPlayer's documentation

  1. ourPlayer初始化状态启动,而不是空闲状态,因为您使用了MediaPlayer.create()

  2. 从状态图中,您只能在播放器正在播放或暂停时调用stop(),但是当您的按钮点击方法第一次运行时,您的播放器才会初始化,因此您的呼叫{{1将你的玩家置于错误状态,而不是停止状态。

  3. 您在错误状态stop()prepare()或可能会被抛出的IOException来电。文档不会在前者被抛出时说出来,而是在IllegalStateException中被捕获。后者会在您第三次单击播放按钮时使您的应用程序崩溃。

  4. 解决方法是仅在播放器播放暂停时调用try-catch,因为这些是直接箭头指向停止状态的状态

    stop()MediaPlayer方法,但没有isPlaying()。可以找到此问题的一些解决方法here

    以下是我提出的解决方案:

    isPaused()

答案 1 :(得分:0)

如果有人和我有完全相同的用例...

只要按下按钮(或触发事件),您只需要从头开始播放声音......

我找到了另一个似乎有用的简单解决方案/解决方法:

@Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // ourPlayer = MediaPlayer.create(this, R.raw.soundeffect);

    }

public void play(View v) {

        if (ourPlayer != null) {
        ourPlayer.release(); }
        ourPlayer = MediaPlayer.create(this, R.raw.soundeffect);
        ourPlayer.start();

    }

如果出于某种原因这是个坏主意,请有人告诉我!谢谢!