我正在开发媒体播放器应用程序,但我有onDestroy方法的问题,我需要继续播放音乐,当我最小化应用程序。但是,当我这样做它停止播放和抛出错误或当我评论它,它是在后台播放但问题是,它甚至当我杀死应用程序时,它不会停止,我可以控制它只是与我的通知控制器,但当我摧毁控制器通过滑动,它正在播放,我在没有音乐播放器的背景音乐。
public class MainActivity extends AppCompatActivity {
private MediaPlayerService player;
private boolean serviceBound = false;
private ArrayList<Audio> audioList;
private RWAdapter rwa;
private RecyclerView rv;
public static final String Broadcast_PLAY_NEW_AUDIO = "com.example.rsabo.mp3player.PlayNewAudio";
public static final String Broadcast_PAUSE_AUDIO= "com.example.rsabo.mp3player.PauseAudio";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
loadAudio();
initRW();
}
private void initRW(){
if (audioList.size()>0) {
rv = (RecyclerView) findViewById(R.id.myRecyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
;
rwa = new RWAdapter(audioList, getApplicationContext());
rv.setAdapter(rwa);
rv.addOnItemTouchListener(new MyTouchListener(this, new onItemClickListener() {
@Override
public void onClick(View view, int index) {
playAudio(index);
}
}));
}
}
//ulozi sa instancia
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("ServiceState", serviceBound);
}
//obnovi sa instancia tam kde bola naposledy ulozena
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
serviceBound = savedInstanceState.getBoolean("ServiceState");
}
//znici instanciu
@Override
protected void onDestroy() {
super.onDestroy();
// if(serviceBound){
// unbindService(serviceConnection);
// player.stopSelf();
// }
}
//viaze tuto triedu s prehravacom, nastavi hodnotu serviceBound na true ked sa vytvori spojenie
private ServiceConnection serviceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
player = binder.getService();
serviceBound = true;
Toast.makeText(MainActivity.this, "Service bound", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
//Metoda pozrie ci je sluzba aktivna,
//ak nie je, do uloziska hodi arraylist s pesnickami, a spusti sluzbu
//ak je vlozi do uloziska novy audioIndex a posle spravu ze ma spustit pesnicku
private void playAudio(int audioIndex){
if(!serviceBound){
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
ulozisko.storeAudio(audioList);
ulozisko.storeAudioIndex(audioIndex);
Intent playerIntent = new Intent(this, MediaPlayerService.class);
startService(playerIntent);
bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} else {
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
ulozisko.storeAudioIndex(audioIndex);
Intent broadcastIntent = new Intent(Broadcast_PLAY_NEW_AUDIO);
sendBroadcast(broadcastIntent);
}
}
private void pauseAudio(){
Intent broadcastIntent = new Intent(Broadcast_PAUSE_AUDIO);
sendBroadcast(broadcastIntent);
}
//nacita pesnicky z mobilu
private void loadAudio() {
ContentResolver contentResolver = getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri, null, selection, null, sortOrder);
if(cursor != null && cursor.getCount() > 0) {
audioList = new ArrayList<>();
while (cursor.moveToNext()){
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
audioList.add(new Audio(data, title, album, artist));
}
}
cursor.close();
}
}
MediaPlayerService
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
private static final int NOTIFICATION_ID = 101;
private MediaSessionManager mediaSessionManager;
private MediaSessionCompat mediaSession;
private MediaControllerCompat.TransportControls transportControls;
private MediaPlayer mediaPlayer;
private String mediaFile;
private int resumePosition;
private AudioManager audioManager;
private boolean hovor = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private ArrayList<Audio> audioList;
private int audioIndex = -1;
private Audio activeAudio;
private final IBinder iBinder = new LocalBinder();
private PlayStatus status;
public static final String ACTION_PLAY = "com.example.rsabo.mp3player.ACTION_PLAY";
public static final String ACTION_PAUSE = "com.example.rsabo.mp3player.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "com.example.rsabo.mp3player.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "com.example.rsabo.mp3player.ACTION_NEXT";
public static final String ACTION_STOP = "com.example.rsabo.mp3player.ACTION_STOP";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
//pri vytvoreni zavola metody callStateListener(),registerJeNahlasReciever(), registerPlayNewAudio()
@Override
public void onCreate() {
super.onCreate();
callStateListener();
registerJeNahlasReciever();
registerPlayNewAudio();
}
//podla priority zvuku v systeme zvysi zvuk, ukonci, zastavi alebo stisi mediaPlayer
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
//metoda na ziskanie AudioFocusu/priority hrania zvuku
private boolean requestAudioFocus() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
//metoda ktora odstrani audioFocus
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == audioManager.abandonAudioFocus(this);
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
}
@Override
public void onCompletion(MediaPlayer mp) {
skipToNext();
buildNotification(PlayStatus.PLAYING);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Log.d("Media Player error", "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK" + extra);
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.d("Media Player error", "MEDIA_ERROR_SERVER_DIED" + extra);
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.d("Media Player error", "MEDIA_ERROR_UNKNOWN" + extra);
break;
}
return false;
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
return false;
}
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
@Override
public void onSeekComplete(MediaPlayer mp) {
}
class LocalBinder extends Binder {
MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
//inicializacia mediaPlayeru, ak sa nenastavi cesta vyhodi chybu a zastavi sa
private void initMediaPlayer() {
if (mediaPlayer == null)
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
// nastavi cestu k hudbe
mediaPlayer.setDataSource(activeAudio.getData());
} catch (IOException e) {
e.printStackTrace();
stopSelf();
}
mediaPlayer.prepareAsync();
}
//nastavenie funkcie tlacidla play
private void playMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
//nastavenie funkcie tlacidla stop
private void stopMedia() {
if (mediaPlayer == null) return;
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
//nastavenie funkcie tlacidla pause
private void pauseMedia() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
resumePosition = mediaPlayer.getCurrentPosition();
}
}
//nastavenie funkcie tlacidla resume
private void resumeMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
}
}
//inicializuje prhravac, ak neziska audiofocus alebo cestu k hudbe zastavi sa
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
audioList = ulozisko.loadAudio();
audioIndex = ulozisko.loadAudioIndex();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
} catch (NullPointerException e) {
stopSelf();
}
if (!requestAudioFocus()) {
stopSelf();
}
if (mediaSessionManager == null) {
try {
initMediaSession();
initMediaPlayer();
} catch (RemoteException e) {
e.printStackTrace();
stopSelf();
}
buildNotification(PlayStatus.PLAYING);
}
handleIncomingActions(intent);
return super.onStartCommand(intent, flags, startId);
}
//metode prida zrusenie audiofocusu a nastavi prehravac na null, vypne phoneStateListener, odregistruje recievre, zmaze notifikaciu a vycisti playlist
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
stopMedia();
mediaPlayer.release();
}
removeAudioFocus();
if (phoneStateListener != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
removeNotification();
unregisterReceiver(jeNahlasReciever);
unregisterReceiver(playNewAudio);
new Ulozisko(getApplicationContext()).clearCacheAudioPlaylist();
}
//ked sa vyberu sluchadla tak sa hranie zastavi
private BroadcastReceiver jeNahlasReciever = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
pauseMedia();
buildNotification(PlayStatus.PAUSED);
}
};
private void registerJeNahlasReciever() {
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(jeNahlasReciever, intentFilter);
}
//metoda ktora zisiti v akom stave je hovor, a ked telefon zvoni alebo prebieha hovor, zastavi prehravanie
private void callStateListener() {
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseMedia();
hovor = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (mediaPlayer != null) {
if (hovor) {
hovor = false;
resumeMedia();
}
}
break;
}
}
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
//ked prepnem pesnicku tak sa pomocou tejto metody resetne prehravac a prepne na dalsiu pesnicku podla indexu ktory dostala v sprave
private BroadcastReceiver playNewAudio = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// if(status == PlayStatus.PAUSED) {
audioIndex = new Ulozisko(getApplicationContext()).loadAudioIndex();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
updateInfo();
buildNotification(PlayStatus.PLAYING);
// } else if (status == PlayStatus.PLAYING){
// pauseMedia();
// updateInfo();
// buildNotification(PlayStatus.PAUSED);
// }
}
};
private void registerPlayNewAudio() {
IntentFilter filter = new IntentFilter(MainActivity.Broadcast_PLAY_NEW_AUDIO);
registerReceiver(playNewAudio, filter);
}
//skontroluje ci mediaSessionManager existuje
//vytvori mediaSession a da mu controller
private void initMediaSession() throws RemoteException {
if (mediaSessionManager != null) return;
mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
mediaSession = new MediaSessionCompat(getApplicationContext(), "Prehravac");
transportControls = mediaSession.getController().getTransportControls();
mediaSession.setActive(true);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
updateInfo();
mediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
super.onPlay();
resumeMedia();
buildNotification(PlayStatus.PLAYING);
}
@Override
public void onPause() {
super.onPause();
pauseMedia();
buildNotification(PlayStatus.PAUSED);
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
skipToNext();
updateInfo();
buildNotification(PlayStatus.PLAYING);
}
@Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
skipToPrevious();
updateInfo();
buildNotification(PlayStatus.PLAYING);
}
@Override
public void onStop() {
super.onStop();
removeNotification();
stopSelf();
}
@Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
}
});
}
//updatne aktualne info o pesnicke
private void updateInfo() {
Bitmap albumArt = BitmapFactory.decodeResource(getResources(), R.drawable.image);
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
//.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, activeAudio.getArtist())
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, activeAudio.getAlbum())
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, activeAudio.getTitle())
.build());
}
//metoda ktora prepne pesnicku na dalsiu, ak je pesnicka posledna tak ju nastavi na prvu v zozname
private void skipToNext() {
if (audioIndex == audioList.size() - 1) {
audioIndex = 0;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(++audioIndex);
}
new Ulozisko(getApplicationContext()).storeAudioIndex(audioIndex);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
//metoda ktora prepne pesnicku dozadu, ak je na zaciatku zoznamu tak ju nastavi na poslednu
private void skipToPrevious() {
if (audioIndex == 0) {
audioIndex = audioList.size() - 1;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(--audioIndex);
}
new Ulozisko(getApplicationContext()).storeAudioIndex(audioIndex);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
//metoda ktora spravi v notifikacnom panely prehravac a vzdy ked sa vola tato metoda tak sa v notifikacii updatne info o pesnicke
private void buildNotification(PlayStatus playStatus) {
int notificationAction = android.R.drawable.ic_media_pause;
PendingIntent playAleboPause = null;
if (playStatus == PlayStatus.PLAYING) {
notificationAction = android.R.drawable.ic_media_pause;
playAleboPause = playbackAction(1);
status = PlayStatus.PLAYING;
} else if (playStatus == PlayStatus.PAUSED) {
notificationAction = android.R.drawable.ic_media_play;
playAleboPause = playbackAction(0);
status = PlayStatus.PAUSED;
}
Bitmap albumArt = BitmapFactory.decodeResource(getResources(), R.drawable.image);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setShowWhen(false)
.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(mediaSession.getSessionToken())
.setShowActionsInCompactView(0, 1, 2))
.setColor(getResources().getColor(R.color.colorPrimary))
//.setLargeIcon(activeAudio.)
.setSmallIcon(android.R.drawable.stat_sys_headset)
.setContentText(activeAudio.getArtist())
.setContentTitle(activeAudio.getTitle())
.setSubText(activeAudio.getAlbum())
.addAction(android.R.drawable.ic_media_previous, "previous", playbackAction(3))
.addAction(notificationAction, "pause", playAleboPause)
.addAction(ic_media_next, "next", playbackAction(2));
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
}
//zmaze notifikaciu
private void removeNotification() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
// nastavenie akcie na tlacidla v notifikacii
private PendingIntent playbackAction(int cisloAkcie) {
Intent akcia = new Intent(this, MediaPlayerService.class);
switch (cisloAkcie) {
case 0:
akcia.setAction(ACTION_PLAY);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 1:
akcia.setAction(ACTION_PAUSE);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 2:
akcia.setAction(ACTION_NEXT);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 3:
akcia.setAction(ACTION_PREVIOUS);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
default:
break;
}
return null;
}
//metoda zisti ktora akcia je aktualna a zavola metodu cez transportControls
private void handleIncomingActions(Intent playbackAction) {
if (playbackAction == null || playbackAction.getAction() == null) return;
String akcia = playbackAction.getAction();
if (akcia.equalsIgnoreCase(ACTION_PLAY)) {
transportControls.play();
} else if (akcia.equalsIgnoreCase(ACTION_PAUSE)) {
transportControls.pause();
} else if (akcia.equalsIgnoreCase(ACTION_NEXT)) {
transportControls.skipToNext();
} else if (akcia.equalsIgnoreCase(ACTION_PREVIOUS)) {
transportControls.skipToPrevious();
} else if (akcia.equalsIgnoreCase(ACTION_STOP)) {
transportControls.stop();
}
}
}
答案 0 :(得分:0)
请尝试startForeground()
Notification.Builder mBuilder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_icon)
.setContentTitle(getString(R.string.title))
.setContentText("");
Intent resultIntent = new Intent(this, ResultIntent.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ParentStack.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int mId = 1489;
startForeground(mId, mBuilder.build());