jofr / capacitor-media-session

Capacitor plugin for media notifications and platform media keys as well as background audio playback.
GNU General Public License v3.0
36 stars 25 forks source link

MediaSession not working on Android #8

Closed woutrikkerink closed 1 year ago

woutrikkerink commented 1 year ago

MediaSession is working flawless in web application, but does not want to show up on Android. It is a Nuxt (vuejs) application using Howler as audio player (in html5 mode). Capacitor version is 4.6.2.

  import { mapState, mapGetters, mapActions } from 'vuex'
  import { MediaSession  } from '@jofr/capacitor-media-session'

  export default {
    render: function (createElement) { },
    computed: {
        ...mapGetters(['station']),
        ...mapState(['paused'])
    },
    methods: {
        ...mapActions(['setStation', 'restoreStation', 'changeStation', 'pauseStation']),
        setMetadata(station) {
          MediaSession.setMetadata({
            title: station.name,
            artist: station.frequency,
            artwork: [
              { src: './assets/chromecast/poster.png',   sizes: '512x512',   type: 'image/png' },
            ]          
          });
        },
        setDefaultMetadata() {
          MediaSession.setMetadata({
            title: "My.App",
            artwork: [
              { src: './assets/chromecast/poster.png',   sizes: '512x512',   type: 'image/png' },
            ]          
          });
        },
        setPlaybackState(state) {
          MediaSession.setPlaybackState({playbackState: state}); 
        }
    },
    watch: {
      station(station) {
        if(station) {
          this.setMetadata(station);
          this.setPlaybackState('playing');
        } else {
          this.setDefaultMetadata();
          this.setPlaybackState('paused');
        }
      },
      paused(paused) {
        this.setPlaybackState(paused ? 'paused' : 'playing');
      }
    },
    mounted() {
      this.setDefaultMetadata();

      MediaSession.setActionHandler({ action: 'play' }, () => {
        console.log('MediaSession play');
        this.restoreStation();
      });

      MediaSession.setActionHandler({ action: 'pause' }, () => {
        console.log('MediaSession pause');
        this.pauseStation();
      });

      MediaSession.setActionHandler({ action: 'previoustrack' }, (details) => {
        console.log('MediaSession previoustrack');
        this.changeStation(-1);
      });

      MediaSession.setActionHandler({ action: 'nexttrack' }, (details) => {
        console.log('MediaSession nexttrack');
        this.changeStation(1);
      });

      MediaSession.setActionHandler({ action: 'stop' }, () => {
        console.log('MediaSession stop');
        this.setStation(null);
      });
    },
    unmounted() {
      MediaSession = null;
    }
  }

Do I need to add something to AndroidManifest and/or MainActivity besides this command?

npm install @jofr/capacitor-media-session
npx cap sync
jofr commented 1 year ago

It should not be necessary to add anything else. The media notification should show up as soon as the playback state is set to "playing" using MediaSession.setPlaybackState({ playbackState: "playing" });. You could try calling this function directly at the start of the app to make sure that it definitely gets called and see if that changes something? What Android version are you testing this on and which version of the plugin are you using? And are there maybe any error or log messages that could relate to this problem?

woutrikkerink commented 1 year ago

Stupid me. I had some code (a level higher) that was checking for MediaSession support before loading the MediaSession module.

      supportsMediaSessionApi() {
        return ('mediaSession' in navigator);
      }

I see your class MediaSessionWeb is doing the same, so I could safely remove this check on my side. Solved. Thanks for your reply.