对于mediasession
大于或等于的 androids 来说效果很好,lollipop
但由于某种原因,使用 mediasession 实现锁屏按钮似乎会导致问题,我的服务中有一个句柄意图方法:
private void handleIntentActions(Intent actionIntent) {
if(actionIntent == null || actionIntent.getAction() == null)return;
String actionString = actionIntent.getAction();
if( actionString.equalsIgnoreCase( ACTION_PPLAY ) || actionString.equalsIgnoreCase(ACTION_PLAY)){
mMediaSessionTransportControls.play();
}else if( actionString.equalsIgnoreCase(ACTION_PAUSE) ){
mMediaSessionTransportControls.pause();
}else if( actionString.equalsIgnoreCase( ACTION_PREVIOUS ) ){
mMediaSessionTransportControls.skipToPrevious();
}else if( actionString.equalsIgnoreCase( ACTION_NEXT ) ){
mMediaSessionTransportControls.skipToNext();
}else if( actionString.equalsIgnoreCase( ACTION_DISMISS ) ){
mMediaSessionTransportControls.stop();
}else if( actionString.equalsIgnoreCase( ACTION_START_FOREGROUND ) ){
createNotificationChannel();
requestAudioFocus();
Log.e("NotifBuildTest", "NotifBUilderBefore: "+notificationBuilder);
Notification notification = notificationBuilder.build();
Log.e("NotifBuildTest", "NotifBUilderAfter: "+notificationBuilder);
notification.flags = NotificationCompat.FLAG_ONGOING_EVENT|NotificationCompat.FLAG_FOREGROUND_SERVICE
| NotificationCompat.FLAG_NO_CLEAR | NotificationCompat.FLAG_HIGH_PRIORITY;
startForeground(APP_NOTIFICATION_ID, notification);
}
该onStartCommand
方法如下所示:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(mService, "foreground onStartCommand executed", Toast.LENGTH_SHORT).show();
handleIntentActions(intent);
updateMetaData("Unknown", "Unknown");
super.onStartCommand(intent, flags, startId);
return START_NOT_STICKY;
}
updateMetaData
看起来像这样:
private void updateMetaData(Bitmap albumArt,String songTitle, String artistName){
mMediaSession.setMetadata( new MediaMetadataCompat.Builder()
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt )
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artistName )
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, songTitle )
.build() );
PlaybackStateCompat mnew = PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_STOP )
.setState(
( getCurrentPlaybackStateCompat(),
0,
1.0f )
.build();
}
initMediaSession
是这样的:
public void initMediaSession() throws RemoteException {
requestAudioFocus();
//ComponentName mRemoteControlResponder = new ComponentName(getPackageName(), MediaButtonReceiver.class.getName());
//final Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
//mediaButtonIntent.setComponent(mRemoteControlResponder);
if(mMediaSessionManager != null)return;
mMediaSession = new MediaSessionCompat(getApplicationContext(), mMediaSessionTag);
mMediaSessionManager = MediaSessionManager.getSessionManager(mService);
mMediaSessionTransportControls = mMediaSession.getController().getTransportControls();
mMediaSession.setActive(true);
//following flags are now set by default;
//mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS |
// MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
updateMetaData("Unknown", "Unknown");
//setCallbacks
mMediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
//super.onPlay();
mService.playEvent();
Toast.makeText(mService.this, "transport play is clicked", Toast.LENGTH_SHORT).show();
updateMetaDataWithCurrentStateDetails();
}
@Override
public void onPause() {
//super.onPause();
mService.pauseEvent();
Toast.makeText(mService.this, "transport pause is clicked", Toast.LENGTH_SHORT).show();
updateMetaDataWithCurrentStateDetails();
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
mService.nextPreviousTrigger(true,true);
updateMetaDataWithCurrentStateDetails();
}
@Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
mService.nextPreviousTrigger(false,true);
updateMetaDataWithCurrentStateDetails();
}
@Override
public void onStop() {
super.onStop(); //stop the service //BOTH METHODS ARE DIFFERENT
removeNotification(); //remove the notification UI
stopSelf();
}
});
mMediaSession.setActive(true);
}
当我单击play
通知中的按钮时,它按预期工作,但是当我单击锁屏的播放按钮一次时,它被单击了两次,
我mediaButtonReceiver
看起来像这样(现在非常简单的实现):
import androidx.media.session.MediaButtonReceiver;
public class medButtonReceiver extends MediaButtonReceiver {
public static int count = 0;
@Override
public void onReceive(Context context, Intent intent) {
Intent mainIntent = null;
if(count++ % 2 ==0) {
mainIntent = new Intent(context, mService.class);
mainIntent.setAction(mService.ACTION_PLAY);
}else{
mainIntent = new Intent(context, mService.class);
mainIntent.setAction(mService.ACTION_PAUSE);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(mainIntent);
} else {
context.startService(mainIntent);
}
Log.e( "xTvM::","medButtonReceiver invoked" );
}
}
运行logcat
看起来像这样:
/com.app.www E/xTvM::: something to click
09-19 09:55:37.608 8422-8422/com.app.www E/PBS::: Current playback state compat: play
09-19 09:55:37.658 8422-8422/com.app.www E/PBS::: Current playback state compat: pause
09-19 09:55:37.668 8422-8422/com.app.www E/PBS::: Current playback state compat: pause
09-19 09:55:37.678 8422-8422/com.app.www E/xTvM::: something to click
09-19 09:55:37.708 8422-8422/com.app.www E/PBS::: Current playback state compat: pause
09-19 09:55:37.778 8422-8422/com.app.www E/PBS::: Current playback state compat: play
09-19 09:55:37.788 8422-8422/com.app.www E/PBS::: Current playback state compat: play
09-19 09:55:37.808 778-778/? E/KeyguardHostView: ensureTransportPresentOrRemoved = 2
09-19 09:55:37.829 778-778/? E/KeyguardHostView: ensureTransportPresentOrRemoved = 2
09-19 09:55:47.628 618-790/? E/lights: write_int failed to open -1
09-19 09:56:00.891 618-875/? E/Watchdog: !@Sync 70
这表明它实际上运行了两次,但我不知道为什么。有人知道为什么会这样吗?提前致谢。