1

对于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

这表明它实际上运行了两次,但我不知道为什么。有人知道为什么会这样吗?提前致谢。

4

0 回答 0