在我的应用中,我想有一个简单的方法,使用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文件夹(使用任何音频文件):
的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'
}
答案 0 :(得分:1)
根据MediaPlayer's documentation:
ourPlayer
以初始化状态启动,而不是空闲状态,因为您使用了MediaPlayer.create()
。
从状态图中,您只能在播放器正在播放或暂停时调用stop()
,但是当您的按钮点击方法第一次运行时,您的播放器才会初始化,因此您的呼叫{{1将你的玩家置于错误状态,而不是停止状态。
您在错误状态stop()
或prepare()
或可能会被抛出的IOException
来电。文档不会在前者被抛出时说出来,而是在IllegalStateException
中被捕获。后者会在您第三次单击播放按钮时使您的应用程序崩溃。
解决方法是仅在播放器播放或暂停时调用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();
}
如果出于某种原因这是个坏主意,请有人告诉我!谢谢!