Momo
Momo

Reputation: 960

Flutter audio_service plugin doesn't play audio

AudioService.play(); throws an error :

java.lang.NullPointerException: Attempt to invoke virtual method 'void io.flutter.plugin.common.MethodChannel.invokeMethod(java.lang.String, java.lang.Object, io.flutter.plugin.common.MethodChannel$Result)' on a null object reference, null, null, null)

Debug stop :

Debug stop

 onPressed: () async {
            if (playing) {
              // AudioService.pause();
            } else {
              AudioService.play();
            }
          },

background_audio.dart

import 'package:audio_service/audio_service.dart';
import 'package:just_audio/just_audio.dart';
import 'package:neodiom/api/_queue.dart' as player;
import 'package:neodiom/models/_Track.dart';

// Must be a top-level function
// void _entrypoint() => AudioServiceBackground.run(() => AudioPlayerTask());

class AudioPlayerTask extends BackgroundAudioTask {
  // the Audio player works fine itself and the problem is not related to it
  final _player = player.queue.player; // just_audio player

  // Implement callbacks here. e.g. onStart, onStop, onPlay, onPause
  onPlay() => _player.play();
  onPause() => _player.pause();
  onSeekTo(Duration duration) => _player.seek(duration);
  onSetSpeed(double speed) => _player.setSpeed(speed);

  onStop() async {
    // Stop and dispose of the player.
    await _player.dispose();
    // Shut down the background task.
    await super.onStop();
  }

  onStart(Map<String, dynamic> params) async {
    print(" **** Starting AudioPlayerTask ...");
    // Tell the UI and media notification what we're playing.
    Track t = player.Samples.tracks[0];
    MediaItem m =
        MediaItem(id: t.getTrack, album: t.album['title'], title: t.title);
    AudioServiceBackground.setMediaItem(m);
    _player.currentIndexStream.listen((index) {
      AudioServiceBackground.setMediaItem(player.queue.currentTrackMediaItem);
    });

    // Listen to state changes on the player...
    _player.playerStateStream.listen((playerState) {
      // ... and forward them to all audio_service clients.
      AudioServiceBackground.setState(
        playing: playerState.playing,
        // Every state from the audio player gets mapped onto an audio_service state.
        processingState: {
          ProcessingState.loading: AudioProcessingState.connecting,
          ProcessingState.buffering: AudioProcessingState.buffering,
          ProcessingState.ready: AudioProcessingState.ready,
          ProcessingState.completed: AudioProcessingState.completed,
        }[playerState.processingState],
        // Tell clients what buttons/controls should be enabled in the
        // current state.
        controls: [
          playerState.playing ? MediaControl.pause : MediaControl.play,
          MediaControl.stop,
        ],
      );
    });
  }
}

entrypoint

void _entrypoint() => AudioServiceBackground.run(() => AudioPlayerTask());

main.dart / Service initializer (during App initState)

 void initBackgroundAudioService() async {
    try {
      await AudioService.connect();
      await AudioService.start(
        backgroundTaskEntrypoint: _entrypoint,
        androidNotificationChannelName: 'Audio Service Demo',
        // Enable this if you want the Android service to exit the foreground state on pause.
        //androidStopForegroundOnPause: true,
        androidNotificationColor: 0xFF2196f3,
        androidNotificationIcon: 'mipmap/ic_launcher',
        androidEnableQueue: true,
      );
    } catch (e) {
      print("** Error on start : $e");
    }
  }

Upvotes: 0

Views: 1106

Answers (1)

Momo
Momo

Reputation: 960

I just had to follow the OS Setups (Android setup instruction in my case) according to the bellow recipe from the documentation

  1. Edit your project's AndroidManifest.xml file to declare the permission to create a wake lock, and add component entries for the <service> and <receiver>:
<manifest ...>
  <uses-permission android:name="android.permission.WAKE_LOCK"/>
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
  
  <application ...>
    
    ...
    
    <service android:name="com.ryanheise.audioservice.AudioService">
      <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService" />
      </intent-filter>
    </service>

    <receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" >
      <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
      </intent-filter>
    </receiver> 
  </application>
</manifest>
  1. Starting from Flutter 1.12, you will need to disable the shrinkResources setting in your android/app/build.gradle file, otherwise the icon resources used in the Android notification will be removed during the build:
android {
    compileSdkVersion 28

    ...

    buildTypes {
        release {
            signingConfig ...
            shrinkResources false // ADD THIS LINE
        }
    }
}

Upvotes: 1

Related Questions