ryanheise / audio_service Goto Github PK
View Code? Open in Web Editor NEWFlutter plugin to play audio in the background while the screen is off.
Flutter plugin to play audio in the background while the screen is off.
Currently, there's no support at all for setting or retrieving ratings. I'm going to start working on this now, and I'll send a pull request when I'm done.
hi, i was trying to add your plugin to a new project in order to run the example, and i have this error:
(i modified the manifest and adding the MainApplication file)
D/AndroidRuntime( 5855): Shutting down VM
E/AndroidRuntime( 5855): FATAL EXCEPTION: main
E/AndroidRuntime( 5855): Process: com.ryanheise.audioserviceexample, PID: 5855
E/AndroidRuntime( 5855): java.lang.NullPointerException: Attempt to invoke interface method 'void io.flutter.plugin.common.PluginRegistry$PluginRegistrantCallback.registerWith(io.flutter.plugin.common.PluginRegistry)' on a null object reference
E/AndroidRuntime( 5855): at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler$3.onPlay(AudioServicePlugin.java:218)
E/AndroidRuntime( 5855): at com.ryanheise.audioservice.AudioService$MediaSessionCallback$1.run(AudioService.java:396)
E/AndroidRuntime( 5855): at com.ryanheise.audioservice.AudioService$MediaSessionCallback.play(AudioService.java:411)
E/AndroidRuntime( 5855): at com.ryanheise.audioservice.AudioService$MediaSessionCallback.onPlay(AudioService.java:394)
E/AndroidRuntime( 5855): at android.support.v4.media.session.MediaSessionCompat$Callback$StubApi21.onPlay(MediaSessionCompat.java:1259)
E/AndroidRuntime( 5855): at android.support.v4.media.session.MediaSessionCompatApi21$CallbackProxy.onPlay(MediaSessionCompatApi21.java:194)
E/AndroidRuntime( 5855): at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1407)
E/AndroidRuntime( 5855): at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime( 5855): at android.os.Looper.loop(Looper.java:164)
E/AndroidRuntime( 5855): at android.app.ActivityThread.main(ActivityThread.java:6494)
E/AndroidRuntime( 5855): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 5855): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
E/AndroidRuntime( 5855): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
i cannot run the example,i can run it only openning the plugin project itself (but obviously that is not the way), what am i doing wrong?
Describe the bug
After hot restart plugin stops working:
E/flutter (22566): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method connect on channel ryanheise.com/audioService)
E/flutter (22566): #0 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:300:7)
E/flutter (22566): <asynchronous suspension>
E/flutter (22566): #1 AudioService.connect (package:audio_service/audio_service.dart:398:20)
E/flutter (22566): <asynchronous suspension>
E/flutter (22566): #2 _MyAppState.connect (package:audio_service_example/main.dart:64:24)
E/flutter (22566): <asynchronous suspension>
E/flutter (22566): #3 _MyAppState.initState (package:audio_service_example/main.dart:39:5)
E/flutter (22566): #4 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3846:58)
E/flutter (22566): #5 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3711:5)
E/flutter (22566): #6 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2956:14)
E/flutter (22566): #7 Element.updateChild (package:flutter/src/widgets/framework.dart:2759:12)
E/flutter (22566): #8 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:933:16)
E/flutter (22566): #9 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:904:5)
E/flutter (22566): #10 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:850:17)
E/flutter (22566): #11 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2253:19)
E/flutter (22566): #12 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:849:13)
E/flutter (22566): #13 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart
:736:7)
E/flutter (22566): #14 runApp (package:flutter/src/widgets/binding.dart:780:7)
E/flutter (22566): #15 main (package:audio_service_example/main.dart:24:16)
E/flutter (22566): #16 _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter (22566): #17 _rootRun (dart:async/zone.dart:1124:13)
E/flutter (22566): #18 _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (22566): #19 _runZoned (dart:async/zone.dart:1516:10)
E/flutter (22566): #20 runZoned (dart:async/zone.dart:1500:12)
E/flutter (22566): #21 _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter (22566): #22 _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
To Reproduce
Steps to reproduce the behavior:
flutter run
on example in repoExpected behavior
Plugin keep working
Runtime Environment (please complete the following information):
Flutter SDK version
[√] Flutter (Channel stable, v1.2.1, on Microsoft Windows [Version 10.0.17134.706], locale ru-RU)
[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[√] Android Studio (version 3.4)
Describe the bug
The main thread is blocked when the plugin loads a new image for the notification.
To Reproduce
This can be observed easily if you turn off wifi/mobile data and add a new MediaItem
. The network request takes a while to time out, and the app is unresponsive while it does.
Expected behavior
The image loading should be entirely asynchronous.
Runtime Environment (please complete the following information):
As the title says, when I stop my service, and then start it again, the transport controls don't work.
Stacktrace:
java.lang.IllegalStateException: onLoadChildren must call detach() or sendResult() before returning for package=com.android.bluetooth id=root
at android.service.media.MediaBrowserService.performLoadChildren(MediaBrowserService.java:708)
at android.service.media.MediaBrowserService.addSubscription(MediaBrowserService.java:638)
at android.service.media.MediaBrowserService.access$500(MediaBrowserService.java:78)
at android.service.media.MediaBrowserService$ServiceBinder$3.run(MediaBrowserService.java:298)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
When in lock screen mode i can press the pause button and the music pauses, then the notification on the lock screen changes to "<- play ->" but my notification should be showing only "play stop". If you unlock the screen you see the notification with the right set of buttons and can play pause etc...
To Reproduce
Steps to reproduce the behavior:
Bug:
Expected behaviour:
Should start playing and show right controls after pause
Screenshots
Notification:
Lock screen:
Lock screen after pressing pause, play doesn't respond:
Notification as it is:
Notification after pressing play:
Runtime Environment (please complete the following information):
Flutter SDK version
Flutter 1.2.1
Flutter doctor:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.2.1, on Mac OS X 10.14.2 18C54, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.3)
[✓] IntelliJ IDEA Community Edition (version 2018.2.4)
[✓] VS Code (version 1.32.3)
[✓] Connected device (2 available)
• No issues found!
Btw this plugin is a great contribution to Flutter, good work!
This is also an issue that Spotify had recently after some android updates.
I'm new to Flutter and I'm doing some research to see if it's in a state to build a music streaming app. I was trying the AudioPlayers library the other day and was impressed with how easy it was to use.
I'm now trying to get this service running, but I had some questions about an advanced configuration involving multiple media players. Specifically I want to make a gapless playback feature by using a second audioplayer instance to cache songs from a server while the current audioplayer instance is playing. Then when the song is finished, the audioplayers can be swapped seamlessly.
It looks like this is doable from what I can tell, but I wanted to see if there's any roadblocks.
I am having a bit of trouble figuring out how to do error handling within the background isolate.
My background task can throw some exceptions when trying to stream audio, and I would like to handle those exceptions in the UI side of things, so the user can be properly informed of what happened.
In case that the app is not opened, I would like to handle these exceptions when the the user opens the app, so probably when AudioService.connect
is called again.
I had hoped to use custom actions to get this information across, but since I can only have custom actions go from the UI isolate to the background isolate, and not the other way around, I am not entirely sure how to approach this.
Any help would be greatly appreciated!
Is your feature request related to a problem? Please describe.
A question. I want to show a play position counter. I thought there was onAudioPositionChanged property which I can define to call a function to update my playbackState, but there is not. I used to do a "onAudioPositionChanged.listen" like the "audioplayers" plugin.
Describe the solution you'd like
A onAudioPositionChanged call back property that I can define, if I was in the right direction.
Describe alternatives you've considered
None.
Additional context
(I have used scoped model and moved playbackState to the model, so as to save the play state between page navigation.)
If I have multiple audio file and want to play next or previous then how can we manage it. Kindly request you to guide us for it.
At the moment (as far as I can tell), the art is only fetched when the song starts playing.
It'd be better if the plugin prefetched art for items in the queue, so there's no delay in showing the art in the notification.
@ryanheise I see that the new version is now on AndroidX. Before I upgrade, I have a question about how this affects the usage of the audioplayer
plugin. I was not able to find any mention of androidx in the audioplayer
github repo, which makes me think it is not supported.
If you're able to provide some clarification on this, I would greatly appreciate it.
Thanks.
Is there any way to use a custom notification?
I'm creating this issue to keep track of an iOS implementation. I myself am an Android developer, and I'd love to see an iOS developer contribute.
This is my app's UI:
As you can see, I have a control bar at the bottom on any screen. If I press stop in the notification, I have no way to know to hide this bar.
I propose we make a stream that sends some special object (or just a boolean) when the service is started and stopped, so we can be notified.
I'm trying to use the plugin in my project. I put 2 files: MainApplication.java and edited AndroidManifest.xml, exatly to the written in Tutorial, but I got this error:
Built build/app/outputs/apk/debug/app-debug.apk.
Syncing files to device Android SDK built for x86...
W/info.radiobasi( 5384): Accessing hidden field Landroid/service/media/MediaBrowserService$Result;->mFlags:I (light greylist, reflection)
D/AndroidRuntime( 5384): Shutting down VM
E/AndroidRuntime( 5384): FATAL EXCEPTION: main
E/AndroidRuntime( 5384): Process: br.com.tecnocampinfo.radiobasic, PID: 5384
E/AndroidRuntime( 5384): java.lang.IllegalStateException: No pluginRegistrantCallback has been set. Make sure you call AudioServicePlugin.setPluginRegistrantCallback(this) from your application's onCreate.
E/AndroidRuntime( 5384): at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler$3.onPlay(AudioServicePlugin.java:224)
E/AndroidRuntime( 5384): at com.ryanheise.audioservice.AudioService$MediaSessionCallback$1.run(AudioService.java:446)
E/AndroidRuntime( 5384): at com.ryanheise.audioservice.AudioService$MediaSessionCallback.play(AudioService.java:461)
E/AndroidRuntime( 5384): at com.ryanheise.audioservice.AudioService$MediaSessionCallback.onPlay(AudioService.java:444)
E/AndroidRuntime( 5384): at android.support.v4.media.session.MediaSessionCompat$Callback$StubApi21.onPlay(MediaSessionCompat.java:1259)
E/AndroidRuntime( 5384): at android.support.v4.media.session.MediaSessionCompatApi21$CallbackProxy.onPlay(MediaSessionCompatApi21.java:194)
E/AndroidRuntime( 5384): at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1486)
E/AndroidRuntime( 5384): at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime( 5384): at android.os.Looper.loop(Looper.java:193)
E/AndroidRuntime( 5384): at android.app.ActivityThread.main(ActivityThread.java:6669)
E/AndroidRuntime( 5384): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 5384): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/AndroidRuntime( 5384): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process ( 5384): Sending signal. PID: 5384 SIG: 9
Lost connection to device.
I use the Simulator, Android 9. Who can help me? Please? =D
Is it possible to open application by tapping on the main notification body (like most Android players do, for example, Google Play Music)?
Crash when run the example code with sdk 28 on Android emulator, The only change is the \android\app\build.gradle file with the "compileSdkVersion 28".
Hello.
In my app I have cover art files stored for each album, they're accessible via url, for example:
http://antennaria.rocks/music/artwork/ecovillage/sacred_world_1d00e34d24e43b4b9bfc1c241f45300a_250x250.jpg
Trying to use setMediaItem(item) method with artUri set to such url (actually, any url I've tried) results in the following exception:
D/AndroidRuntime( 9000): Shutting down VM
E/AndroidRuntime( 9000): FATAL EXCEPTION: main
E/AndroidRuntime( 9000): Process: com.antennaria.gimpobox, PID: 9000
E/AndroidRuntime( 9000): java.lang.IllegalArgumentException: Unsupported value: http://antennaria.rocks/music/artwork/ecovillage/sacred_world_1d00e34d24e43b4b9bfc1c241f45300a_250x250.jpg
E/AndroidRuntime( 9000): at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:293)
E/AndroidRuntime( 9000): at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:290)
E/AndroidRuntime( 9000): at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:282)
E/AndroidRuntime( 9000): at io.flutter.plugin.common.StandardMethodCodec.encodeMethodCall(StandardMethodCodec.java:36)
E/AndroidRuntime( 9000): at io.flutter.plugin.common.MethodChannel.invokeMethod(MethodChannel.java:83)
E/AndroidRuntime( 9000): at io.flutter.plugin.common.MethodChannel.invokeMethod(MethodChannel.java:70)
E/AndroidRuntime( 9000): at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler.invokeMethod(AudioServicePlugin.java:417)
E/AndroidRuntime( 9000): at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler$1.onMetadataChanged(AudioServicePlugin.java:71)
E/AndroidRuntime( 9000): at android.support.v4.media.session.MediaControllerCompat$Callback$StubApi21.onMetadataChanged(MediaControllerCompat.java:832)
E/AndroidRuntime( 9000): at android.support.v4.media.session.MediaControllerCompatApi21$CallbackProxy.onMetadataChanged(MediaControllerCompatApi21.java:297)
E/AndroidRuntime( 9000): at android.media.session.MediaController$MessageHandler.handleMessage(MediaController.java:1089)
E/AndroidRuntime( 9000): at android.os.Handler.dispatchMessage(Handler.java:108)
E/AndroidRuntime( 9000): at android.os.Looper.loop(Looper.java:166)
E/AndroidRuntime( 9000): at android.app.ActivityThread.main(ActivityThread.java:7425)
E/AndroidRuntime( 9000): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 9000): at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
E/AndroidRuntime( 9000): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
I/Process ( 9000): Sending signal. PID: 9000 SIG: 9
Lost connection to device.
To be sure that url is valid I've used Uri.encodeFull() but no avail. Also I've tried to put hard-coded urls to various images from the internet to no avail as well.
Did you try artUri functionality by yourself? Did it work at all? What I do wrong?
I am new in flutter and try to make a simple radio app, please help to solve the problem below.
Thank you.
Describe the bug
Fail to play stream when I just simply modify the example code, to make it click different's button to play different's online stream.
To Reproduce
click button 'AudioPlayer1' it will use Uri1 as stream source to play.
click button 'AudioPlayer2' it will use Uri2 as stream source to play.
Expected behavior
To play Uri1 / Uri2 audio stream.
Flutter SDK version
[√] Flutter (Channel beta, v1.4.9-hotfix.1, on Microsoft Windows [Version 10.0.17763.437], locale en-US)
• Flutter version 1.4.9-hotfix.1 at C:\flutter
• Framework revision 88fa7ea403 (11 days ago), 2019-04-11 14:01:46 -0700
• Engine revision 4737fc5cd8
• Dart version 2.2.1 (build 2.2.1-dev.4.1 None)
[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
• Android SDK at C:\ProgramData\AndroidStudio
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• ANDROID_HOME = C:\ProgramData\AndroidStudio
• Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1343-b01)
• All Android licenses accepted.
[√] Android Studio (version 3.4)
• Android Studio at C:\Program Files\Android\Android Studio
• Flutter plugin version 34.0.2
• Dart plugin version 183.5901
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1343-b01)
[!] IntelliJ IDEA Community Edition (version 2019.1)
• IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1
X Flutter plugin not installed; this adds Flutter specific functionality.
X Dart plugin not installed; this adds Dart specific functionality.
• For information about installing plugins, see
https://flutter.io/intellij-setup/#installing-the-plugins
[√] VS Code, 64-bit edition (version 1.33.1)
• VS Code at C:\Program Files\Microsoft VS Code
• Flutter extension version 2.25.1
[√] Connected device (1 available)
• Android SDK built for x86 • emulator-5554 • android-x86 • Android 9 (API 28) (emulator)
** Code: **
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:audio_service/audio_service.dart';
MediaControl playControl = MediaControl(
androidIcon: 'drawable/ic_action_play_arrow',
label: 'Play',
action: MediaAction.play,
);
MediaControl pauseControl = MediaControl(
androidIcon: 'drawable/ic_action_pause',
label: 'Pause',
action: MediaAction.pause,
);
MediaControl stopControl = MediaControl(
androidIcon: 'drawable/ic_action_stop',
label: 'Stop',
action: MediaAction.stop,
);
String streamUri = '';
const Uri1 = 'https://5b2959fe11444.streamlock.net/radio/am1430.stream/playlist.m3u8';
const Uri2 = 'https://stmw.rthk.hk/vod/_definst_/rthkweb/smil:sub_spots__5c244fc5e3463.smil/manifest.m3u8';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
@OverRide
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State with WidgetsBindingObserver {
PlaybackState _state;
StreamSubscription _playbackStateSubscription;
@OverRide
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
connect();
}
@OverRide
void dispose() {
disconnect();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@OverRide
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
connect();
break;
case AppLifecycleState.paused:
disconnect();
break;
default:
break;
}
}
void connect() async {
await AudioService.connect();
if (_playbackStateSubscription == null) {
_playbackStateSubscription = AudioService.playbackStateStream
.listen((PlaybackState playbackState) {
setState(() {
_state = playbackState;
});
});
}
}
void disconnect() {
if (_playbackStateSubscription != null) {
_playbackStateSubscription.cancel();
_playbackStateSubscription = null;
}
AudioService.disconnect();
}
@OverRide
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Audio Service Demo'),
),
body: new Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _state?.basicState == BasicPlaybackState.playing
? [pauseButton(), stopButton()]
: _state?.basicState == BasicPlaybackState.paused
? [playButton(), stopButton()]
: [startButton('AudioPlayer1', _backgroundAudioPlayerTask, Uri1), startButton('AudioPlayer2', _backgroundAudioPlayerTask, Uri2)],
),
),
),
);
}
RaisedButton startButton(String label, Function backgroundTask, String Uri) {
streamUri = Uri;
return RaisedButton(
child: Text(label),
onPressed: () {
AudioService.start(
backgroundTask: backgroundTask,
resumeOnClick: true,
androidNotificationChannelName: 'Audio Service Demo',
notificationColor: 0xFF2196f3,
androidNotificationIcon: 'mipmap/ic_launcher',
);
},
);
}
IconButton playButton() => IconButton(
icon: Icon(Icons.play_arrow),
iconSize: 64.0,
onPressed: AudioService.play,
);
IconButton pauseButton() => IconButton(
icon: Icon(Icons.pause),
iconSize: 64.0,
onPressed: AudioService.pause,
);
IconButton stopButton() => IconButton(
icon: Icon(Icons.stop),
iconSize: 64.0,
onPressed: AudioService.stop,
);
}
void _backgroundAudioPlayerTask() async {
CustomAudioPlayer player = CustomAudioPlayer();
AudioServiceBackground.run(
onStart: player.run,
onPlay: player.play,
onPause: player.pause,
onStop: player.stop,
onClick: (MediaButton button) => player.playPause(),
);
}
class CustomAudioPlayer {
AudioPlayer _audioPlayer = new AudioPlayer();
Completer _completer = Completer();
Future run() async {
MediaItem mediaItem = MediaItem(
id: 'audio_1',
album: 'Sample Album',
title: 'Sample Title',
artist: 'Sample Artist');
AudioServiceBackground.setMediaItem(mediaItem);
var playerStateSubscription = _audioPlayer.onPlayerStateChanged
.where((state) => state == AudioPlayerState.COMPLETED)
.listen((state) {
stop();
});
play();
await _completer.future;
playerStateSubscription.cancel();
}
void playPause() {
if (AudioServiceBackground.state.basicState == BasicPlaybackState.playing)
pause();
else
play();
}
void play() {
_audioPlayer.play(streamUri);
AudioServiceBackground.setState(
controls: [pauseControl, stopControl],
basicState: BasicPlaybackState.playing,
);
}
void pause() {
_audioPlayer.pause();
AudioServiceBackground.setState(
controls: [playControl, stopControl],
basicState: BasicPlaybackState.paused,
);
}
void stop() {
_audioPlayer.stop();
AudioServiceBackground.setState(
controls: [],
basicState: BasicPlaybackState.stopped,
);
_completer.complete();
}
}
I'm having an issue with the new stream apis, where setState
is being called after my widget is disposed. I can't work out what I've done wrong.
Relevant code:
void connect() async {
AudioService.connect();
playbackStateSubscription?.cancel();
playbackStateSubscription = AudioService.playbackStateStream.listen((PlaybackState playbackState) {
setState(() {
_playbackState = playbackState;
print(playbackState);
});
});
}
void stopListening() {
playbackStateSubscription?.cancel();
playbackStateSubscription = null;
}
@override
void initState() {
super.initState();
connect();
}
@override
void dispose() {
stopListening();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
connect();
break;
case AppLifecycleState.paused:
stopListening();
AudioService.disconnect();
break;
default:
break;
}
}
As media items do not seem to contain any information about what to play (such as a streaming URL), I am trying to provide the background task with this information using the AudioService.customAction
function.
After this, I would like to initiate playing with AudioService.play
, roughly as such:
Map<String, String> sources = { 'mediaId': 'exampleUrl' };
await AudioService.customAction('addMediaSources', sources);
await AudioService.play();
However, it seems so that sometimes the onPlay
callback in the background task is called before the onCustomAction
callback completes. Because of this, there is yet no source to play from by the time the onPlay
callback is called.
When adding a bit of a delay between the customAction
and play
calls, everything functions as normal.
It seems that the future returned by customAction
can complete before the actual completion of the callback. Is it possible to change this behaviour, or is there maybe some other way I can wait for the custom action to complete before moving on?
Is it possible to connect in two widgets at once, and have both receive callbacks?
I have my queue viewing screen, and I also have a media control bar.
When AudioServiceBackground.setMediaItem
is called twice in a row for a MediaItem with the same id, the changes to the media item in the second call are not reflected in the item coming out of AudioService.currentMediaItemStream
. Instead, the media item from the first call is output another time.
When the id differs between the first and second call, it does behave as expected.
I run into this issue when attempting to update the duration. In my situation when the onPlay callback is called, the media item is set with setMediaItem
, but the duration is still unknown as the item is being streamed. As soon as the duration is known by the audio player, I copy the MediaItem with the new duration included and call AudioServiceBackground.setMediaItem
once again. However, as the MediaItem id is still the same, AudioService.currentMediaItemStream
does not provide the new duration.
I have setup the plugin but when try to play app force close.
i have setup from example provided and using same audio plugin also.
java.lang.IllegalStateException: registrar.activity() must not be null
at com.fuyumi.flutterstatusbarcolor.flutterstatusbarcolor.FlutterStatusbarcolorPlugin$Companion.registerWith(FlutterStatusbarcolorPlugin.kt:18)
at com.fuyumi.flutterstatusbarcolor.flutterstatusbarcolor.FlutterStatusbarcolorPlugin.registerWith(Unknown Source:2)
at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:34)
at com.thebridges.thebridgesapp.MainApplication.registerWith(MainApplication.java:17)
at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler$4.onPlay(AudioServicePlugin.java:258)
at com.ryanheise.audioservice.AudioService$MediaSessionCallback$1.run(AudioService.java:525)
at com.ryanheise.audioservice.AudioService$MediaSessionCallback.play(AudioService.java:541)
at com.ryanheise.audioservice.AudioService$MediaSessionCallback.onPlay(AudioService.java:523)
at android.support.v4.media.session.MediaSessionCompat$Callback$StubApi21.onPlay(MediaSessionCompat.java:1259)
at android.support.v4.media.session.MediaSessionCompatApi21$CallbackProxy.onPlay(MediaSessionCompatApi21.java:194)
at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1416)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:6656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v1.2.1, on Mac OS X 10.13.6 17G65, locale en-IN)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.3)
I'm guilty of creating this bug - I made the streams API, but I'm too busy to fix it at the moment. (Sorry.)
When the future returned by the service's starting function is completed, the streams and variables should be cleared.
I know It is no problem with audio_service
, but I don't know who ask. I try use this plugin together to google_maps_flutter: ^0.0.3+3
, but I obtened this error:
W/info.radiobasi( 7357): Accessing hidden field Landroid/service/media/MediaBrowserService$Result;->mFlags:I (light greylist, reflection)
D/AndroidRuntime( 7357): Shutting down VM
E/AndroidRuntime( 7357): FATAL EXCEPTION: main
E/AndroidRuntime( 7357): Process: br.com.tecnocampinfo.radiobasic, PID: 7357
E/AndroidRuntime( 7357): java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference
E/AndroidRuntime( 7357): at io.flutter.plugins.googlemaps.GoogleMapsPlugin.<init>(GoogleMapsPlugin.java:90)
Anyone can help me? I tried to search and modify the code in the plugin, but I do not had a good result.
Thanks for everything, Your plugin guaranteed one job to sustent my family =)
Is your feature request related to a problem? Please describe.
I'm building a Pandora client. In a nutshell, Pandora lets you have different stations, with different kinds of music chosen for you on each one. In my UI, I need to access the playing station's name and id.
Describe the solution you'd like
IIRC, Android lets you save simple data like strings and integers in a bundle in the MediaSession
itself. We can create functions in the AudioServiceBackground
and AudioService
classes to set/get the data respectively. Perhepas we could go even futher than the Android API and use streams as well.
Describe alternatives you've considered
Right now, I'm using the genre field in the playing MediaItem
to hold this data, by storing it in the format id||stationName
. This is a bad solution because the station name could (although it is unlikely) have a double pipe in it. I've though of some other solutions:
SendPort
s, but it would be very cumbersome, with a lot of boilerplate.When the background service is running and playing an item, if I call AudioService.stop(), then play() on a new item, I call the AudioServiceBackground.setMediaItem() method and get the following error:
03:58:49.305 90 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): Failed to handle method call
03:58:49.305 91 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String[] java.lang.String.split(java.lang.String)' on a null object reference
03:58:49.305 92 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.ryanheise.audioservice.AudioService.getResourceId(AudioService.java:136)
03:58:49.305 93 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.ryanheise.audioservice.AudioService.buildNotification(AudioService.java:188)
03:58:49.305 94 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.ryanheise.audioservice.AudioService.updateNotification(AudioService.java:285)
03:58:49.305 95 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.ryanheise.audioservice.AudioService.setMetadata(AudioService.java:398)
03:58:49.305 96 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.ryanheise.audioservice.AudioServicePlugin$BackgroundHandler.onMethodCall(AudioServicePlugin.java:543)
03:58:49.305 97 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:201)
03:58:49.305 98 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl.handleMessageFromDart(FlutterNativeView.java:188)
03:58:49.305 99 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:202)
03:58:49.305 100 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at android.os.MessageQueue.nativePollOnce(Native Method)
03:58:49.305 101 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at android.os.MessageQueue.next(MessageQueue.java:326)
03:58:49.305 102 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at android.os.Looper.loop(Looper.java:160)
03:58:49.305 103 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at android.app.ActivityThread.main(ActivityThread.java:6680)
03:58:49.305 104 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at java.lang.reflect.Method.invoke(Native Method)
03:58:49.305 105 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
03:58:49.305 106 info flutter.tools E/MethodChannel#ryanheise.com/audioServiceBackground(31568): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Any help or ideas on what could be wrong would be greatly appreciated.
Nothing happens when I run this code:
AudioService.start(
backgroundTask: audioTask,
notificationChannelName: "Media",
);
No notification is shown, and the service is not shown as a running service in the developer settings. This code, however, still prints true:
AudioService.running.then((bool running) {
print(running);
});
Further, when I call AudioService.play()
, I get an exception thrown from the JVM:
Attempt to invoke virtual method 'android.support.v4.media.session.MediaControllerCompat$TransportControls android.support.v4.media.session.MediaControllerCompat.getTransportControls()' on a null object reference.
I don't know if this is a bug, but "registered" is never printed with this code in my application class:
public class MainApplication : FlutterApplication(), PluginRegistry.PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
println("onCreate!!!")
AudioServicePlugin.setPluginRegistrantCallback(this)
}
override fun registerWith(registry: PluginRegistry) {
println("registered!!!")
GeneratedPluginRegistrant.registerWith(registry)
}
}
There's no way to get the playback state or queue synchronously, on demand. Perhaps this can be done by simply caching them in a variable when the plugin receives them? I'll make a pull request.
I'm using the androidNotificationChannelName:
but nothing happening in the notification.
AudioService.connect();
AudioService.start(
backgroundTask: _backgroundAudioPlayerTask,
resumeOnClick: true,
androidNotificationChannelName: 'ABC Rádio',
notificationColor: 0x5E6263,
androidNotificationIcon: 'mipmap/radio',
);
Anyone can help me? =D
Hello, thanks for the great plugin. It's not the easiest one to use but potential is enormous. Now I am in the process of rewriting my custom player to use your plugin and will file the issues on the way :-)
The first one may looks minor but anyway maybe it is easy to fix. Notification layout is a bit sloppy: Track / Album information is displayed right under the Notification Channel / Icon row without any padding which looks a bit ugly. In comparison, several standard notifications are displayed more accurate. Please see attached screenshot to spot the difference.
Hello everyone,
I'm creating an application that requires background audio and I came across this library. The problem is that I don't understand how everything works together. Reading the example didn't help me a lot and I don't want to copy paste and adjust things since I will maintain it later. I will leave a brief example of how I coded that part.
I'm already using AudioPlayer library to play audio and I'm trying to use it with this library.
This library plays audio or just help the AudioPlayer play even if locked?
Sorry if I'm a bit annoying, I'm new to flutter and those libraries too
The problem with that problem is that nothing happens, no error no audio.
Frontend widget:
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
AudioService.connect();
break;
case AppLifecycleState.paused:
AudioService.disconnect();
break;
default:
break;
}
}
new IconButton(
onPressed: () => state == AudioPlayerState.PLAYING ? pause() : play(urlAudio),
iconSize: 26.0,
icon: state == AudioPlayerState.PLAYING ? new Icon(Icons.pause) : new Icon(Icons.play_arrow),
color: Colors.cyan)
play(String URL) {
urlAudio = URL;
AudioService.play();
}
Background Audio Worker:
AudioServiceBackground.run(
onStart: () async {
// do i need to do something here?
},
onPlay: () async {
if(_songs != null && _songs.length > 0) {
if(isPlaying) {
await super.stop();
}
if(_songs.length > _indexSong) {
_indexSong = _indexSong;
await super.play(_songs[_indexSong], isLocal: false);
} else {
_indexSong = 0;
await super.play(_songs[0], isLocal: false);
}
}
},
onPause: () async {
if(state == AudioPlayerState.PLAYING) {
await super.pause();
}
},
onStop: () {
// Your custom dart code to stop audio playback.
},
onClick: (MediaButton button) {
// Your custom dart code to handle a media button click.
}
);
}
I am using the flutter_inappbrowser plugin in my project, as well as audioservice.
If I open a browser view before ever starting the audio service, all is okay, but if I start the audio service, then open the browser, the app crashes with the error:
08:54:03.581 145 info flutter.tools E/AndroidRuntime(31364): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
The call stack stops around here:
08:54:03.583 148 info flutter.tools E/AndroidRuntime(31364): at com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity.show(InAppBrowserActivity.java:309)
08:54:03.583 149 info flutter.tools E/AndroidRuntime(31364): at com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity.prepareView(InAppBrowserActivity.java:98)
08:54:03.583 150 info flutter.tools E/AndroidRuntime(31364): at com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity.onCreate(InAppBrowserActivity.java:69)
I suspect this could be related to audioservice requiring a custom MainApplication class, but I don't have much Android development experience, so any insight/help would be much appreciated.
browser plugin: https://github.com/pichillilorenzo/flutter_inappbrowser
The example has a hardcoded audio file URL, and since the backgroundTask callback is in an isolate, I am unable to pass the correct URL to the AudioPlayer.
How can I pass a dynamic file path to the audio player in the BackgroundTask callback?
I was thinking to use isolate ports in the backgroundTask, but not sure if thats the correct way, or if it would even work (im new to flutter/dart)
Thanks.
Fail to update the example project to Gradle 4.6 and Android Studio Gradle plugin 3.2.0.
When launching a release APK with this plugin, the app crashes on start.
It works fine when debugging normally with Android Studio & IntelliJ.
This too happens to the example app included.
Steps to reproduce:
flutter build apk --release
flutter install
The following exception is thrown:
01-06 01:39:35.691 21844 21844 D AndroidRuntime: Shutting down VM
01-06 01:39:25.272 21788 21788 E AndroidRuntime: FATAL EXCEPTION: main
01-06 01:39:25.272 21788 21788 E AndroidRuntime: Process: com.ryanheise.audioserviceexample, PID: 21788
01-06 01:39:25.272 21788 21788 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke interface method 'void io.flutter.plugin.common.MethodChannel$Result.success(java.lang.Object)' on a null object reference
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler.sendConnectResult(AudioServicePlugin.java:148)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler.access$500(AudioServicePlugin.java:69)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler$3.onConnected(AudioServicePlugin.java:122)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.support.v4.media.MediaBrowserCompat$ConnectionCallback$StubApi21.onConnected(MediaBrowserCompat.java:651)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.support.v4.media.MediaBrowserCompatApi21$ConnectionCallbackProxy.onConnected(MediaBrowserCompatApi21.java:102)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.media.browse.MediaBrowser$6.run(MediaBrowser.java:603)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:873)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.os.Looper.loop(Looper.java:193)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6863)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
01-06 01:39:25.272 21788 21788 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Please, I'm new to flutter and I'm building a music app, I found your plugin helpful and I'm fetching songs from an API and I need to pass URL so that when the music is playing, it will also show in the notification panel, but I have not been able to do so.
This is what i want to do:
class CustomAudioPlayer {
streamUri = url.link;
AudioPlayer _audioPlayer = new AudioPlayer();
Completer _completer = Completer();
Future run() async {
MediaItem mediaItem = MediaItem(
id: '',
album: '',
title: url.title,
artist: url.artist
);
AudioServiceBackground.setMediaItem(mediaItem);
var playerStateSubscription = _audioPlayer.onPlayerStateChanged
.where((state) => state == AudioPlayerState.COMPLETED)
.listen((state) {
stop();
});
play();
await _completer.future;
playerStateSubscription.cancel();
}
void playPause() {
if (AudioServiceBackground.state.basicState == BasicPlaybackState.playing)
pause();
else
play();
}
void play() {
_audioPlayer.play(streamUri);
AudioServiceBackground.setState(
controls: [pauseControl, stopControl],
basicState: BasicPlaybackState.playing,
);
}
void pause() {
_audioPlayer.pause();
AudioServiceBackground.setState(
controls: [playControl, stopControl],
basicState: BasicPlaybackState.paused,
);
}
void stop() {
_audioPlayer.stop();
AudioServiceBackground.setState(
controls: [],
basicState: BasicPlaybackState.stopped,
);
_completer.complete();
}
}
I know the Android docs say to make the notification dismissable when the audio's paused, but I find this annoying because it's too easy to stop the service with the "clear all" button in the notification tray. I prefer to have a stop action in my notification.
It'd be great have an option to keep the notification non-dismissable when the audio's paused.
Hi,
i want add a "Slider" to your example (https://github.com/ryanheise/audio_service/blob/master/example/lib/main.dart) which will continue to work as the program closes and re-runs.
But i can not setup this feature
Please guide me and send me the relevant codes.
Thank you very much for your support
Hello!
While experimenting with this plugin, I ran into the issue that whenever I call AudioService.addQueueItem
, the following exception is thrown:
E/MethodChannel#ryanheise.com/audioService(11872): Failed to handle method call
E/MethodChannel#ryanheise.com/audioService(11872): java.lang.UnsupportedOperationException: This session doesn't support queue management operations
E/MethodChannel#ryanheise.com/audioService(11872): at android.support.v4.media.session.MediaControllerCompat$MediaControllerImplApi21.addQueueItem(MediaControllerCompat.java:1988)
E/MethodChannel#ryanheise.com/audioService(11872): at android.support.v4.media.session.MediaControllerCompat.addQueueItem(MediaControllerCompat.java:316)
E/MethodChannel#ryanheise.com/audioService(11872): at com.ryanheise.audioservice.AudioServicePlugin$ClientHandler.onMethodCall(AudioServicePlugin.java:316)
E/MethodChannel#ryanheise.com/audioService(11872): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:200)
E/MethodChannel#ryanheise.com/audioService(11872): at io.flutter.view.FlutterNativeView.handlePlatformMessage(FlutterNativeView.java:163)
E/MethodChannel#ryanheise.com/audioService(11872): at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#ryanheise.com/audioService(11872): at android.os.MessageQueue.next(MessageQueue.java:326)
E/MethodChannel#ryanheise.com/audioService(11872): at android.os.Looper.loop(Looper.java:160)
E/MethodChannel#ryanheise.com/audioService(11872): at android.app.ActivityThread.main(ActivityThread.java:6863)
E/MethodChannel#ryanheise.com/audioService(11872): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#ryanheise.com/audioService(11872): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
E/MethodChannel#ryanheise.com/audioService(11872): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
This error was produced with the following code, based off the example in this repo:
https://gist.github.com/BeMacized/5ccc11f43c4b18bd1e40a1e539082721
Any idea what might cause this?
Hello.
While main audio management work is now handled in background task I am curious how the launching app should know about played track duration and (most important) current position (to display seek bar).
AudioPlayer plugin which I use for actual playing provides convenient streams / properties to get all this information but how to pass this information back from background task is a question. As far as I understand it's now impossible because the only hooks you can made into background task are those in the AudioService.connect() method and all of them are unsuitable for the task. After discovering this I hoped that I will be able to utilize custom action functionality you provide but this turned out to be custom action FROM AudioService to background task and not in the opposite direction.
Of course I can hack the system with some kind of communication solution (like using Shared Preferences or even file system) but this looks inefficient and smelly....
What do you think? Best regards!
I have some problems to use audioplayer
and found the flutter_radio
. This plugin solve my problems, but don't work fine in audio_service
.
I adapted the Exemple Code for use flutter_radio
@override
void initState() {
super.initState();
AudioService.connect();
AudioService.start(
backgroundTask: _backgroundAudioPlayerTask,
resumeOnClick: true,
androidNotificationChannelName: 'ABC Rádio',
notificationColor: 0x5E6263,
androidNotificationIcon: 'mipmap/radio',
);
}
and
void _backgroundAudioPlayerTask() async {
CustomAudioPlayer player = CustomAudioPlayer();
AudioServiceBackground.run(
onStart: player.run,
onPlay: player.play,
onPause: player.pause,
onStop: player.stop,
onClick: (MediaButton button) => player.playPause(),
);
}
class CustomAudioPlayer {
bool _playing;
Future<void> run() async {
MediaItem mediaItem = MediaItem(
id: 'audio_1', album: 'ABC Radio', title: 'A rádio que não cansa vc');
AudioServiceBackground.setMediaItem(mediaItem);
audioStart();
play();
}
Future<void> audioStart() async {
await FlutterRadio.audioStart();
print('Audio Start OK');
}
void playPause() {
if (_playing)
pause();
else
play();
}
void play() {
FlutterRadio.play(url: streamUrl);
_playing = true;
AudioServiceBackground.setState(
controls: [pauseControl, stopControl],
basicState: BasicPlaybackState.playing);
buttonState = !buttonState;
}
void pause() {
FlutterRadio.playOrPause(url: streamUrl);
AudioServiceBackground.setState(
controls: [playControl, stopControl],
basicState: BasicPlaybackState.paused);
}
void stop() {
FlutterRadio.playOrPause(url: streamUrl);
AudioServiceBackground.setState(
controls: [], basicState: BasicPlaybackState.stopped);
buttonState = !buttonState;
}
}
The audio start normally in initState
, the notification start, but not fixed, closing fast after starter. The audio continue playing normally.
The log in the starter app is:
I/ExoPlayerImpl(30320): Init abad60d [ExoPlayerLib/2.8.2] [ASUS_Z012D, ASUS_Z012DC, asus, 26]
D/EventBus(30320): No subscribers registered for event class java.lang.String
D/EventBus(30320): No subscribers registered for event class org.greenrobot.eventbus.NoSubscriberEvent
D/EventBus(30320): No subscribers registered for event class java.lang.String
D/EventBus(30320): No subscribers registered for event class org.greenrobot.eventbus.NoSubscriberEvent
D/NetworkSecurityConfig(30320): No Network Security Config specified, using platform default
I/DpmTcmClient(30320): RegisterTcmMonitor from: com.android.okhttp.TcmIdleTimerMonitor
W/VideoCapabilities(30320): Unrecognized profile 2130706433 for video/avc
W/VideoCapabilities(30320): Unrecognized profile 2130706434 for video/avc
The project repository is here: https://github.com/thyagoluciano/flutter_radio
Why can I do to work the flutter_radio
in audio_service
?
Good getlocaltime()!
I'm struggling to pass any data to _backgroundAudioPlayerTask
function (according to this example https://github.com/ryanheise/audio_service/blob/master/example/lib/main.dart). I want to pass URL to play.
var res = AudioService.start(
backgroundTask: () async {
// I modified CustomAudioPlayer also
CustomAudioPlayer player = CustomAudioPlayer("HERE IS MY URL");
AudioServiceBackground.run(
onStart: player.run,
onPlay: player.play,
onPause: player.pause,
onStop: player.stop,
onClick: (MediaButton button) => player.playPause(),
);
},
// omited
);
But it doesn't work. It returns instance of Future<bool>
which resolves to false:
I/flutter (19613): Instance of 'Future<bool>'
I/flutter (19613): false
I also was trying to do something like this:
Function play(String url) {
void handler() async {
CustomAudioPlayer player = CustomAudioPlayer(url);
AudioServiceBackground.run(
onStart: player.run,
onPlay: player.play,
onPause: player.pause,
onStop: player.stop,
onClick: (MediaButton button) => player.playPause(),
);
}
return handler;
}
Error:
E/flutter (20407): [ERROR:flutter/shell/common/shell.cc(184)] Dart Error: Unhandled exception:
E/flutter (20407): NoSuchMethodError: No top-level getter 'handler' declared.
E/flutter (20407): Receiver: top-level
E/flutter (20407): Tried calling: handler
E/flutter (20407): #0 NoSuchMethodError._throwNew (dart:core/runtime/liberrors_patch.dart:212:5)
E/flutter (20407): [ERROR:flutter/shell/common/engine.cc(178)] Could not run the isolate.
E/flutter (20407): [ERROR:flutter/shell/common/engine.cc(119)] Engine not prepare and launch isolate.
E/flutter (20407): [ERROR:flutter/shell/platform/android/android_shell_holder.cc(167)] Could not launch engine in configuration.
Can you help me please, what I'm doing wrong?
p.s: I'm new to dart and flutter, so maybe I'm doing something really stupid :)
Here is the logs of the build
`Launching lib/main.dart on iPhone Xʀ in debug mode...
Running pod install...
CocoaPods' output:
↳
Preparing
Analyzing dependencies
Inspecting targets to integrate
Using `ARCHS` setting to build architectures of target `Pods-Runner`: (``)
Finding Podfile changes
A audio_service
A audioplayer
- Flutter
- flutter_downloader
- package_info
- path_provider
- url_launcher
Fetching external sources
-> Fetching podspec for `Flutter` from `.symlinks/flutter/ios`
-> Fetching podspec for `audio_service` from `.symlinks/plugins/audio_service/ios`
[!] No podspec found for `audio_service` in `.symlinks/plugins/audio_service/ios`
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/external_sources/path_source.rb:14:in `block in fetch'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/user_interface.rb:85:in `titled_section'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/external_sources/path_source.rb:11:in `fetch'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer/analyzer.rb:697:in `fetch_external_source'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer/analyzer.rb:673:in `block (2 levels) in fetch_external_sources'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer/analyzer.rb:672:in `each'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer/analyzer.rb:672:in `block in fetch_external_sources'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/user_interface.rb:64:in `section'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer/analyzer.rb:671:in `fetch_external_sources'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer/analyzer.rb:85:in `analyze'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer.rb:243:in `analyze'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer.rb:154:in `block in resolve_dependencies'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/user_interface.rb:64:in `section'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer.rb:153:in `resolve_dependencies'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/installer.rb:116:in `install!'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/command/install.rb:41:in `run'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/claide-1.0.2/lib/claide/command.rb:334:in `run'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/lib/cocoapods/command.rb:52:in `run'
/usr/local/Cellar/cocoapods/1.5.3/libexec/gems/cocoapods-1.5.3/bin/pod:55:in `<top (required)>'
/usr/local/Cellar/cocoapods/1.5.3/libexec/bin/pod:22:in `load'
/usr/local/Cellar/cocoapods/1.5.3/libexec/bin/pod:22:in `<main>'
Error output from CocoaPods:
↳
[!] Automatically assigning platform `ios` with version `10.0` on target `Runner` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.
Error running pod install
Error launching application on iPhone Xʀ.
`
I want start the notification in app initialization, but don't play anything. I try, in the example, put this code in "initState":
@override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); connect(); AudioService.start( backgroundTask: _backgroundAudioPlayerTask, resumeOnClick: true, notificationChannelName: 'Audio Service Demo', notificationColor: 0xFF2196f3, androidNotificationIcon: 'mipmap/ic_launcher', ); }
But don't working. Anyone can help me? =D
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.