working media player on android

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-29 03:43:23 +00:00
co-authored by Copilot
parent 34476a56da
commit 38f4769d2d
7 changed files with 79 additions and 10 deletions
+29 -1
View File
@@ -1,4 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:label="kryz_go_flutter"
android:name="${applicationName}"
@@ -30,6 +37,27 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<service
android:name="com.ryanheise.audioservice.AudioService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="mediaPlayback"
tools:ignore="Instantiatable">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<receiver
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
android:enabled="true"
android:exported="true"
tools:ignore="Instantiatable">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON"/>
</intent-filter>
</receiver>
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
@@ -1,5 +1,5 @@
package com.example.kryz_go_flutter
import io.flutter.embedding.android.FlutterActivity
import com.ryanheise.audioservice.AudioServiceActivity
class MainActivity : FlutterActivity()
class MainActivity : AudioServiceActivity()
+4
View File
@@ -26,6 +26,10 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
+28 -6
View File
@@ -1,14 +1,35 @@
import 'package:flutter/material.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'streaming_audio_business_object.dart';
void main() {
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await JustAudioBackground.init(
androidNotificationChannelId: 'com.kryzgoflutter.audio.channel',
androidNotificationChannelName: 'KRYZ Audio Playback',
androidNotificationOngoing: true,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final StreamingAudioBusinessObject _audio = StreamingAudioBusinessObject();
@override
void dispose() {
_audio.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
@@ -16,21 +37,23 @@ class MyApp extends StatelessWidget {
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey),
),
home: const MainPage(),
home: MainPage(audio: _audio),
debugShowCheckedModeBanner: false,
);
}
}
class MainPage extends StatefulWidget {
const MainPage({super.key});
const MainPage({super.key, required this.audio});
final StreamingAudioBusinessObject audio;
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
final StreamingAudioBusinessObject _audio = StreamingAudioBusinessObject();
StreamingAudioBusinessObject get _audio => widget.audio;
@override
void initState() {
@@ -59,7 +82,6 @@ class _MainPageState extends State<MainPage> {
@override
void dispose() {
_audio.removeListener(_handleAudioStateChanged);
_audio.dispose();
super.dispose();
}
+11 -1
View File
@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:just_audio/just_audio.dart';
class StreamingAudioBusinessObject extends ChangeNotifier {
@@ -28,7 +29,16 @@ class StreamingAudioBusinessObject extends ChangeNotifier {
Future<void> play() async {
if (!_isSourceLoaded) {
await _player.setUrl(streamUrl);
await _player.setAudioSource(
AudioSource.uri(
Uri.parse(streamUrl),
tag: const MediaItem(
id: 'kryz-live-stream',
title: 'KRYZ Live Stream',
artist: 'KRYZ Radio',
),
),
);
_isSourceLoaded = true;
}
@@ -5,10 +5,14 @@
import FlutterMacOS
import Foundation
import audio_service
import audio_session
import just_audio
import sqflite_darwin
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}
+1
View File
@@ -35,6 +35,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
just_audio: ^0.10.5
just_audio_background: ^0.0.1-beta.17
dev_dependencies:
flutter_test: