working media player on android
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -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
|
<application
|
||||||
android:label="kryz_go_flutter"
|
android:label="kryz_go_flutter"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
@@ -30,6 +37,27 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
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>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
<!-- Required to query activities that can process text, see:
|
||||||
https://developer.android.com/training/package-visibility and
|
https://developer.android.com/training/package-visibility and
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package com.example.kryz_go_flutter
|
package com.example.kryz_go_flutter
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import com.ryanheise.audioservice.AudioServiceActivity
|
||||||
|
|
||||||
class MainActivity : FlutterActivity()
|
class MainActivity : AudioServiceActivity()
|
||||||
|
|||||||
@@ -26,6 +26,10 @@
|
|||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>audio</string>
|
||||||
|
</array>
|
||||||
<key>UIApplicationSceneManifest</key>
|
<key>UIApplicationSceneManifest</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>UIApplicationSupportsMultipleScenes</key>
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
|
|||||||
+28
-6
@@ -1,14 +1,35 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:just_audio_background/just_audio_background.dart';
|
||||||
|
|
||||||
import 'streaming_audio_business_object.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());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatefulWidget {
|
||||||
const MyApp({super.key});
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
@@ -16,21 +37,23 @@ class MyApp extends StatelessWidget {
|
|||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey),
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey),
|
||||||
),
|
),
|
||||||
home: const MainPage(),
|
home: MainPage(audio: _audio),
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainPage extends StatefulWidget {
|
class MainPage extends StatefulWidget {
|
||||||
const MainPage({super.key});
|
const MainPage({super.key, required this.audio});
|
||||||
|
|
||||||
|
final StreamingAudioBusinessObject audio;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MainPage> createState() => _MainPageState();
|
State<MainPage> createState() => _MainPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MainPageState extends State<MainPage> {
|
class _MainPageState extends State<MainPage> {
|
||||||
final StreamingAudioBusinessObject _audio = StreamingAudioBusinessObject();
|
StreamingAudioBusinessObject get _audio => widget.audio;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -59,7 +82,6 @@ class _MainPageState extends State<MainPage> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_audio.removeListener(_handleAudioStateChanged);
|
_audio.removeListener(_handleAudioStateChanged);
|
||||||
_audio.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:just_audio_background/just_audio_background.dart';
|
||||||
import 'package:just_audio/just_audio.dart';
|
import 'package:just_audio/just_audio.dart';
|
||||||
|
|
||||||
class StreamingAudioBusinessObject extends ChangeNotifier {
|
class StreamingAudioBusinessObject extends ChangeNotifier {
|
||||||
@@ -28,7 +29,16 @@ class StreamingAudioBusinessObject extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<void> play() async {
|
Future<void> play() async {
|
||||||
if (!_isSourceLoaded) {
|
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;
|
_isSourceLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,14 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import audio_service
|
||||||
import audio_session
|
import audio_session
|
||||||
import just_audio
|
import just_audio
|
||||||
|
import sqflite_darwin
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
|
||||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||||
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
||||||
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ dependencies:
|
|||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
just_audio: ^0.10.5
|
just_audio: ^0.10.5
|
||||||
|
just_audio_background: ^0.0.1-beta.17
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user