我是Android新手。我试图创建一个音乐播放器,它将根据计数播放特定的MP3(由Rc
变量控制)并基于按钮序列(由BitCount
变量控制)应该改变。我点击了一个停止按钮,我可以停止音乐。
我的问题是,当UI处于前台时,一切正常,但是当屏幕进入后台时,音乐也开始运行(它可以让音乐在后台运行)但是当我再次从后台运行我的UI时前景比点击停止按钮我无法停止音乐,它会持续运行。当我正在旋转我的手机时,会发生同样的问题。
代码:
package com.example.tallite;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Toast;
public class MainActivity extends Activity implements OnSeekBarChangeListener {
MediaPlayer OurSong;
public Handler handler1 = new Handler();
Button Start;
Button Stop;
Button Button21;
Button Button22;
Button StopButton;
public int GProgreess=0;
int Rc=0;
int BitCount=6;
int SeekPos=0;
int Period=500;
int BreakVar=0;
Thread myThread ;
public TextView text1,text2,text3,text4;
private SeekBar bar;
private TextView textProgress,textAction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "onCreate()", Toast.LENGTH_LONG).show();
text1 = (TextView)findViewById(R.id.textbit1);
text2 = (TextView)findViewById(R.id.textbit2);
text3 = (TextView)findViewById(R.id.textbit3);
text4 = (TextView)findViewById(R.id.textbit4);
Button21=(Button)findViewById(R.id.button21);
Button22=(Button)findViewById(R.id.button22);
StopButton=(Button)findViewById(R.id.buttonstop);
bar = (SeekBar)findViewById(R.id.seekBar1);
textProgress = (TextView)findViewById(R.id.textViewProgress);
OurSong=MediaPlayer.create(MainActivity.this,R.raw.a);
try {
OurSong.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bar.setOnSeekBarChangeListener(this); // set seekbar listener.
/*handler1.post(runnable1);
stopPlaying();*/
StopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopPlaying();
BitCount=5;
handler1.removeCallbacks(runnable1);
}/****End of on clk******/
});/*****End of set on clk listener*****/
Button21.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopPlaying();
Rc=0;
BitCount=13;
handler1.removeCallbacks(runnable1);
handler1.post(runnable1);
}/****End of on clk******/
});/*****End of set on clk listener*****/
Button22.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopPlaying();
Rc=0;
BitCount=15;
handler1.removeCallbacks(runnable1);
handler1.post(runnable1);
}/****End of on clk******/
});/*****End of set on clk listener*****/
}
@Override
protected void onStart() {
//the activity is become visible.
super.onStart();
/*handler1.removeCallbacks(runnable1);*/
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStop() {
//the activity is no longer visible.
super.onStop();
Toast.makeText(this, "onStop()", Toast.LENGTH_LONG).show();
}
@Override
protected void onDestroy() {
//The activity about to be destroyed.
super.onDestroy();
Toast.makeText(this, "onDestroy()", Toast.LENGTH_LONG).show();
}
private void stopPlaying()
{
if (OurSong != null)
{
OurSong.stop();
OurSong.release();
OurSong = null;
}
}
/* private void stopPlaying()
{
OurSong.stop();
OurSong.release();
}*/
public Runnable runnable1= new Runnable() {
@Override
public void run() {
if(BitCount==13)
{
text1.setText("1");
text2.setText(""+Rc);
text3.setText(""+BitCount);
if(Rc==0||Rc==6||Rc==10)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.a);
OurSong.start();
}
if(Rc==2||Rc==4||Rc==8||Rc==12)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.b);
OurSong.start();
}
if(Rc==13)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.c);
OurSong.start();
}
Rc++;
if(Rc>BitCount)
{
text4.setText(""+Rc);
Rc=0;
}
}/****End of bitcount=13****/
if(BitCount==15)
{
text1.setText("2");
text2.setText(""+Rc);
text3.setText(""+BitCount);
if(Rc==0||Rc==8||Rc==12)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.a);
OurSong.start();
}
if(Rc==2||Rc==4||Rc==6||Rc==10||Rc==14)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.b);
OurSong.start();
/* Toast.makeText(getApplicationContext(), "-",
Toast.LENGTH_LONG).show();*/
}
if(Rc==15)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.c);
OurSong.start();
/*Toast.makeText(getApplicationContext(), "|",
Toast.LENGTH_LONG).show();*/
}
Rc++;
if(Rc>BitCount)
{
text4.setText(""+Rc);
Rc=0;
}
}/***End of bitcount=15***/
if(BitCount==5)
{
text1.setText("Rc"+Rc);
stopPlaying();
}
if(BitCount==6)
{
text1.setText("x"+Rc);
stopPlaying();
}
handler1.postDelayed(runnable1, Period);
}
};
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
GProgreess=progress+20;
textProgress.setText("Bit/Minute: "+(progress+20));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
seekBar.setSecondaryProgress(seekBar.getProgress());
SeekPos=GProgreess;
Period=(int)(30000/SeekPos);
/*textProgress.setText("Period: "+Period);*/
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
答案 0 :(得分:3)
当您关闭应用时,您的活动会被销毁,因此对您的媒体播放器变量的引用会丢失。当您重新创建ur活动时,您将获得一组新的引用,因此您无法阻止它。
您必须创建一个名为MediaPlayerService的服务名称,它将处理所有与媒体相关的操作,如播放,暂停等。
您可以在此处阅读有关服务的信息: http://developer.android.com/guide/components/services.html
如果你想要一个媒体播放器的例子,你可以查看RandomMusicPlayer,这是android在android示例项目中提供的一个优秀的媒体播放器示例。
以下是我的MediaPlayerService实现
MediaPlayerService类:
package com.cyberinsane.musicplayerlibrary;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
public class MediaPlayerService extends Service implements OnCompletionListener, OnPreparedListener, OnErrorListener {
private static final int NOTIFICATION_ID = 1;
public static final String INTENT_URL = "url";
public enum MediaState {
Playing, Paused, Stopped
}
private MediaState mState = MediaState.Stopped;
private MediaPlayer mPlayer;
private NotificationManager mNotificationManager;
public String mCurrentUrl = "";
public static final String ACTION_TOGGLE_PLAYBACK = "com.cyberinsane.musicplayerlibrary.action.TOGGLE_PLAYBACK";
public static final String ACTION_PLAY = "com.cyberinsane.musicplayerlibrary.action.PLAY";
public static final String ACTION_PAUSE = "com.cyberinsane.musicplayerlibrary.action.PAUSE";
public static final String ACTION_STOP = "com.cyberinsane.musicplayerlibrary.action.STOP";
@Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
String url = intent.getExtras().getString(INTENT_URL);
if (url != null) {
if (!url.equals(mCurrentUrl)) {
mCurrentUrl = url;
mState = MediaState.Stopped;
relaxResources(true);
processPlayRequest();
} else {
if (action.equals(ACTION_TOGGLE_PLAYBACK)) {
processTogglePlaybackRequest();
} else if (action.equals(ACTION_PLAY)) {
processPlayRequest();
} else if (action.equals(ACTION_PAUSE)) {
processPauseRequest();
} else if (action.equals(ACTION_STOP)) {
processStopRequest(false);
}
}
}
}
return START_STICKY;
}
private void processTogglePlaybackRequest() {
if (mState == MediaState.Paused || mState == MediaState.Stopped) {
processPlayRequest();
} else {
processPauseRequest();
}
}
private void processPlayRequest() {
try {
if (mState == MediaState.Stopped) {
createMediaPlayerIfNeeded();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(getApplicationContext(), Uri.parse(mCurrentUrl));
mPlayer.prepare();
} else if (mState == MediaState.Paused) {
mState = MediaState.Playing;
setUpAsForeground("Playing...");
if (!mPlayer.isPlaying()) {
mPlayer.start();
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioPlay();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void processPauseRequest() {
if (mState == MediaState.Playing) {
mState = MediaState.Paused;
mPlayer.pause();
relaxResources(false);
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioPause();
}
}
}
private void processStopRequest(boolean force) {
if (mState == MediaState.Playing || mState == MediaState.Paused || force) {
mState = MediaState.Stopped;
relaxResources(true);
stopSelf();
}
}
private void createMediaPlayerIfNeeded() {
if (mPlayer == null) {
mPlayer = new MediaPlayer();
mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
} else
mPlayer.reset();
}
private void relaxResources(boolean releaseMediaPlayer) {
stopForeground(true);
if (releaseMediaPlayer && mPlayer != null) {
mPlayer.reset();
mPlayer.release();
mPlayer = null;
}
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(getApplicationContext(), "Media player error! Resetting.", Toast.LENGTH_SHORT).show();
Log.e("MusicPlayer", "Error: what=" + String.valueOf(what) + ", extra=" + String.valueOf(extra));
mState = MediaState.Stopped;
relaxResources(true);
if (mIMediaPlayer != null) {
mIMediaPlayer.onError();
}
return true; // true indicates we handled the error
}
@Override
public void onPrepared(MediaPlayer mp) {
mState = MediaState.Playing;
updateNotification("Playing...");
if (!mPlayer.isPlaying()) {
mPlayer.start();
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioPlay();
}
}
}
@Override
public void onCompletion(MediaPlayer mp) {
mState = MediaState.Stopped;
relaxResources(true);
stopSelf();
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioStop();
}
}
/**
* Updates the notification.
*/
private void updateNotification(String text) {
mNotificationManager.notify(NOTIFICATION_ID, buildNotification(text).build());
}
private void setUpAsForeground(String text) {
startForeground(NOTIFICATION_ID, buildNotification(text).build());
}
private NotificationCompat.Builder buildNotification(String text) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this.getApplicationContext());
builder.setSmallIcon(R.drawable.ic_launcher)
.setOngoing(true)
.setContentTitle("Cyberinsane MusicPlayer")
.setContentText(text)
.setContentIntent(
PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(),
MediaPlayerActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
.setContentInfo("Awesome");
return builder;
}
@Override
public void onDestroy() {
mState = MediaState.Stopped;
relaxResources(true);
}
public class LocalBinder extends Binder {
MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
private IMediaPlayer mIMediaPlayer;
public MediaPlayer getMediaPlayer() {
return mPlayer;
}
public void setIMediaPlayer(IMediaPlayer mediaPlayer) {
mIMediaPlayer = mediaPlayer;
}
public MediaState getMediaState() {
return mState;
}
public boolean isPlaying() {
return (mState == MediaState.Playing);
}
public String getCurrentUrl() {
return mCurrentUrl;
}
public long duration() {
if (mPlayer != null) {
return mPlayer.getDuration();
}
return 0;
}
public long position() {
if (mPlayer != null) {
return mPlayer.getCurrentPosition();
}
return 0;
}
public void seekTo(long position) {
if (mPlayer != null) {
mPlayer.seekTo((int) position);
}
}
}
MediaPlayerActivity类:
package com.cyberinsane.musicplayerlibrary;
import java.io.File;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class MediaPlayerActivity extends Activity implements IMediaPlayer {
private ImageButton mButtonPlay;
private EditText mEditTextUrl;
private SeekBar mSeekBarProgress;
private boolean mIsBound;
private String mExtStorePath;
private MediaPlayerService mMediaService;
private Handler mSeekHandler = new Handler();
private Runnable mSeekRunnable = new Runnable() {
@Override
public void run() {
seekStartUpdation();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.media_player_activity);
mButtonPlay = (ImageButton) findViewById(R.id.buttonPlay);
mEditTextUrl = (EditText) findViewById(R.id.editTextURL);
mSeekBarProgress = (SeekBar) findViewById(R.id.seekBarMediaProgress);
mExtStorePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
doBindService();
initListeners();
}
private void initListeners() {
mButtonPlay.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String urlExt = mEditTextUrl.getText().toString();
if (urlExt != null && !urlExt.equals("")) {
String url = mExtStorePath + urlExt;
startService(new Intent(MediaPlayerService.ACTION_TOGGLE_PLAYBACK).putExtra(
MediaPlayerService.INTENT_URL, url));
}
}
});
mSeekBarProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mMediaService.seekTo(seekBar.getProgress());
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// empty
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// empty
}
});
}
@Override
protected void onResume() {
super.onResume();
doBindService();
}
@Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
@Override
protected void onPause() {
super.onPause();
doUnbindService();
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
mMediaService = ((MediaPlayerService.LocalBinder) service).getService();
mMediaService.setIMediaPlayer(MediaPlayerActivity.this);
setControlState();
}
@Override
public void onServiceDisconnected(ComponentName className) {
mMediaService = null;
}
};
private void doBindService() {
bindService(new Intent(MediaPlayerActivity.this, MediaPlayerService.class), mConnection,
Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
@Override
public void onAudioPlay() {
setPlayerState(true);
}
@Override
public void onAudioPause() {
setPlayerState(false);
}
@Override
public void onAudioStop() {
setPlayerState(false);
mSeekBarProgress.setProgress(0);
}
@Override
public void onError() {
// handle errors here
}
private void setControlState() {
if (mMediaService.isPlaying()) {
mEditTextUrl.setText(mMediaService.getCurrentUrl().replace(mExtStorePath, ""));
setPlayerState(true);
} else {
setPlayerState(false);
}
}
public void setPlayerState(boolean isPlaying) {
if (isPlaying) {
mButtonPlay.setImageResource(R.drawable.ic_pause);
mSeekBarProgress.setMax((int) mMediaService.duration());
seekStartUpdation();
} else {
mButtonPlay.setImageResource(R.drawable.ic_play);
seekStopUpdate();
}
}
public void seekStartUpdation() {
mSeekBarProgress.setProgress((int) mMediaService.position());
mSeekHandler.postDelayed(mSeekRunnable, 1000);
}
public void seekStopUpdate() {
mSeekHandler.removeCallbacks(mSeekRunnable);
}
}
媒体播放器事件监听器
package com.cyberinsane.musicplayerlibrary;
public interface IMediaPlayer {
public void onAudioPlay();
public void onAudioPause();
public void onAudioStop();
public void onError();
}
最后是我的清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyberinsane.musicplayerlibrary"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.cyberinsane.musicplayerlibrary.MediaPlayerActivity"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.cyberinsane.musicplayerlibrary.MediaPlayerService"
android:exported="false" >
<intent-filter>
<action android:name="com.cyberinsane.musicplayerlibrary.action.TOGGLE_PLAYBACK" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.PLAY" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.PAUSE" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.SKIP" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.REWIND" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.STOP" />
</intent-filter>
</service>
</application>
</manifest>