java - 在 android 的媒体播放器库中出现问题
问题描述
我正在尝试制作一个音乐应用程序,它可以从 firebase 加载 Song Url 、 Song name 和 Artist name 。我有两个活动,一个是 ExtrasActivity。ExtrasActivity 包含一个 recyclerview,它将歌曲加载到列表中,当我们单击项目时,它会将 songUrl、SongName 和 ArtistName 发送到另一个名为 StackActivity 的活动。我在 StackActivity 中遇到问题,例如在播放歌曲时,如果我返回单击并播放另一首歌曲,那么有时它可以正常工作,但有时它会一起播放两首歌曲。我尝试了很多方法来解决这个问题,但它们都不能正常工作我认为我的 StackActivity 有问题。
这是我的 StackActivity:-
public class StackActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener {
private MediaPlayer mediaPlayer;
private Boolean isPlaying = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stack_activity_name);
SeekBar Song_playing_seekbar;
TextView songInfoSong = findViewById(R.id.song_info_song);
TextView songInfoArtist = findViewById(R.id.song_info_artist);
songInfoSong.setText(getIntent().getStringExtra("Name"));
songInfoArtist.setText(getIntent().getStringExtra("Artist"));
mediaPlayer = new MediaPlayer();
playSong();
}
private void playSong() {
final FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageReference = storage.getReferenceFromUrl(getIntent().getStringExtra("SongUrl"));
storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
try {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
final String url = uri.toString();
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(StackActivity.this);
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i("TAg", "aFailed");
}
});
}
@Override
public void onPrepared(final MediaPlayer mediaPlayer) {
CheckIfSongIsPlayingOrNot();
if (isPlaying == false) {
mediaPlayer.start();
} else if (isPlaying == true) {
mediaPlayer.stop();
}
}
private void CheckIfSongIsPlayingOrNot() {
if (mediaPlayer.isPlaying()) {
isPlaying = true;
} else if (!mediaPlayer.isPlaying()) {
isPlaying = false;
}
}
因此,如果您发现任何问题,请帮助我改进这一点。
解决方案
这是因为MediaPlayer
每次启动StackActivity
. 我什至想知道为什么这不会每次都发生。更准确地说,旧MediaPlayer
实例永远不会停止,甚至更重要的是不会释放。您应该仔细查看MediaPlayer 文档以了解这些状态。
但是对于这种特定情况,我会尝试定义一个 MediaPlayer Singleton。
public class MediaPlayerSingleton implements MediaPlayer.OnPreparedListener {
private static MediaPlayerSingleton instance = null;
private MediaPlayer mediaPlayer = null;
private MediaPlayerSingleton() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(this);
}
public static MediaPlayerSingleton getInstance() {
if (instance == null) {
instance = new MediaPlayerSingleton();
}
return instance;
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
resume();
}
/**
* This will load the given URL into the media player.
* @param url The URL string from the Firebase Uri.
*/
public void play(String url) {
try {
mediaPlayer.reset()
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause() {
mediaPlayer.pause();
}
public void resume() {
mediaPlayer.start();
}
public void stop() {
mediaPlayer.stop();
}
public void release() {
mediaPlayer.release();
}
}
然后,您可以在 StackActivity 中使用它。
public class StackActivity extends AppCompatActivity {
// your onCreate() but leave out the MediaPlayer references
private void playSong() {
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageReference = storage.getReferenceFromUrl(getIntent().getStringExtra("SongUrl"));
storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
MediaPlayerSingleton.getInstance().play(uri.toString());
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i("TAg", "aFailed");
}
});
}
}
但请务必release()
在您的起始活动onDestroy()
(例如ExtrasActivity
)中调用此单例的函数,如下所示:
@Override
protected void onDestroy() {
super.onDestroy();
MediaPlayerSingleton.getInstance().release();
}
必须这样做以释放内存。
只是我提供的单例示例的旁注。这只是一个可以改进的简单示例,例如对 MediaPlayer 实例进行额外的空检查。但它应该给你一点基础。
推荐阅读
- machine-learning - 试图理解随机森林的回归
- xml - 预定义 XML 的 XSD 引发 Cvc-elt.1.a: Cannot Find The Declaration Of Element 错误
- sql - 使用派生表的 SQL 子查询 - 嵌套
- python - 如何用 Numpy 数组替换 For 循环和 IF 语句
- javascript - 如何下载 html 页面,包括 JS 所做的更改
- angular6 - 如何使用 Angular 6 + Handsontable 根据另一个单元格值仅更改一个单元格值?
- vue.js - 可以为 Vuex 模块、突变和动作使用 ES6 类吗?
- c# - 为什么 CompareTo 不使用 ASCII 代码排序对我的字符串进行排序?
- responsive-design - Bootstrap Shopify 导航不会崩溃
- sql-server - 实现 TSQL 函数“自定义值集中的值”的最有效方法