【发布时间】:2023-07-09 22:13:01
【问题描述】:
我的应用程序有 3 个活动(MainPageActivity、FavoritesActivity、SettingsActivity)和一个服务(StreamService)。
MainPageActivity 和FavoritesActivity 底部都有两个按钮:一个用于播放/停止流(网络收音机),另一个用于收藏当前歌曲。当各自的活动处理音乐控件时,这两个都工作得很好,但我决定将它们移到扩展 Service 的类中,因为这是音乐播放器的常见做法。
下面是一些sn-ps的代码:
MainPageActivity:
public void play (View v)
{
Intent intent = new Intent(MainPageActivity.this, EdenService.class);
if (!service.isPlaying())
{
startService(intent);
btnPlay.setText("Stop");
}
else
{
stopService(intent);
btnPlay.setText("Play");
}
}
public void fave (View v)
{
try
{
String currentSong = txtCurrentSong.getText().toString();
if (!db.alreadyFavorited(currentSong))
{
if (!currentSong.isEmpty() || !currentSong.equals("Unavailable"))
{
db.addAnonymousFavorite(currentSong);
Toast.makeText(getApplicationContext(), "Song has been added to favorites.", Toast.LENGTH_LONG).show();
btnFave.setText("Unfave");
}
else
Toast.makeText(getApplicationContext(), "Song title cannot be empty.", Toast.LENGTH_LONG).show();
}
else
{
try
{
db.removeAnonymousFavorite(currentSong);
Toast.makeText(getApplicationContext(), "Song has been removed from favorites.", Toast.LENGTH_LONG).show();
btnFave.setText("Fave");
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), "Could not add song to favorites.", Toast.LENGTH_LONG).show();
Log.e("playButton", Log.getStackTraceString(e));
}
}
//used in onResume for navigation within the app
private void setPlayButtonText()
{
if (!service.isPlaying())
btnPlay.setText("Play");
else
btnPlay.setText("Stop");
}
private void setFaveButtonText()
{
runnable = new Runnable() {
@Override
public void run() {
final String currentSong = ServiceHandler.getCurrentSong();
if (!Settings.isAuthenticated(getApplicationContext()))
{
if (!db.alreadyFavorited(currentSong))
btnFave.setText("Fave");
else
btnFave.setText("Unfave");
handler.postDelayed(this, 3000);
}
}
};
runnable.run();
}
FavoritesActivity 具有相同的代码。
StreamService:
public StreamService()
{
this.mp = new MediaPlayer();
isPlaying = false;
}
@Override
public void onCreate ()
{
try
{
mc = new MediaController(this);
mp.setDataSource(streamLink);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mc.setMediaPlayer(this);
mp.prepareAsync();
Log.d(TAG + ".onCreate()", Boolean.toString(isPlaying));
}
catch (Exception e)
{
Log.e(TAG, Log.getStackTraceString(e));
Toast.makeText(getApplicationContext(), "Could not connect to stream.", Toast.LENGTH_LONG).show();
}
}
@Override
public void onDestroy()
{
pause();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
isPlaying = true;
new Thread(new Runnable()
{
@Override
public void run() {
start();
}
}).start();
return Service.START_STICKY;
}
@Override
public void start() {
try
{
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mp.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
String errorText = "";
switch (what) {
//what = 1
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
errorText += "Error has occured: ";
break;
//what = 100
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
errorText += "Server has died. ";
break;
}
switch (extra) {
//extra = -1004
case MediaPlayer.MEDIA_ERROR_IO:
errorText += "Please check your internet connection.";
break;
//extra = -110
case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
errorText += "Connection has timed out.";
break;
}
Toast.makeText(getApplicationContext(), errorText, Toast.LENGTH_LONG).show();
return true;
}
});
Intent intent = new Intent(this, MainPageActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
Notification notification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Eden Radio")
.setContentText(ServiceHandler.getCurrentSong())
.setSmallIcon(R.drawable.ic_stat_av_play)
.setContentIntent(pi).build();
startForeground(CLASS_ID, notification);
}
catch (Exception e)
{
Log.e(TAG, e.getMessage());
Toast.makeText(getApplicationContext(), "Could not connect to stream.", Toast.LENGTH_LONG).show();
}
}
@Override
public void pause() {
mp.stop();
stopForeground(true);
isPlaying = false;
}
@Override
public boolean isPlaying() {
//mp.isPlaying() always returns false for some reason
return isPlaying; //and so does this
}
现在,我的问题是:service.isPlaying() 总是返回 false,所以当我按下播放键时音乐开始播放,但我永远无法停止音乐。为什么会这样?我已经尝试从服务中创建一个单例(并在尝试 Service 时发现它本身就是一个单例,尽管我仍然不确定它是如何工作的),我我尝试制作isPlaying 字段及其对应的方法isPlaying()static,但无济于事。通过流播放时发出的通知、通过其他活动以及通过销毁和重新启动应用程序访问MainPageActivity 只会导致播放按钮重新初始化为“播放”,并且永远无法停止流。同样的事情发生在FavoritesActivity。
我花了太多时间试图弄清楚为什么它永远不会返回正确的值。如果您能帮助我,我将不胜感激。
提前致谢。
【问题讨论】:
标签: android service android-mediaplayer foreground