void main() async { WidgetsFlutterBinding.ensureInitialized(); final handler = await AudioService.init( builder: () => RadioHandler(), config: const AudioServiceConfig( androidNotificationChannelId: 'com.fmarenas.online.audio', androidNotificationChannelName: 'FM Arenas Online', androidNotificationOngoing: true, androidStopForegroundOnPause: true, ), ); runApp(FmArenasApp(handler: handler)); }
class FmArenasApp extends StatelessWidget { final AudioHandler handler; const FmArenasApp({super.key, required this.handler});
@override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'FM Arenas Online', theme: ThemeData( useMaterial3: true, brightness: Brightness.dark, colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFFFFA726), brightness: Brightness.dark, ), ), home: HomePage(handler: handler), ); } }
class HomePage extends StatelessWidget { final AudioHandler handler; HomePage({super.key, required this.handler});
final Uri website = Uri.parse('https://fmarenas1975.github.io/FM-ARENAS-ONLINE/'); final Uri facebook = Uri.parse('https://www.facebook.com/100092439705105/?locale=es_LA'); final Uri whatsapp = Uri.parse('https://wa.me/54938048058890?text=Hola%20FM%20ArenasPIDETUCANCIONFAVORITA');
Future _open(Uri url) async {https://zeno.fm/radio/fmarenas/ if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { throw 'No se pudo abrir $url'; } }
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF0F172A), Color(0xFF111827), Color(0xFF1F2937)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: ListView( padding: const EdgeInsets.all(20), children: [ const SizedBox(height: 8), Center( child: Container( width: 110, height: 110, decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(28), ), child: const Icon(Icons.radio, size: 58, color: Color(0xFFFFA726)), ), ), const SizedBox(height: 18), const Center( child: Text( 'FM ARENAS ONLINE', style: TextStyle(fontSize: 28, fontWeight: FontWeight.w800), ), ), const SizedBox(height: 6), const Center( child: Text( 'La Rioja, Argentina', style: TextStyle(color: Colors.white70), ), ), const SizedBox(height: 22), _InfoCard( title: 'En vivo ahora', text: 'Escuchá la radio desde tu celular con una experiencia moderna y simple.', ), const SizedBox(height: 14), _PlayerControls(handler: handler), const SizedBox(height: 14), Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: () => _open(website), icon: const Icon(Icons.language), label: const Text('Sitio web'), style: ElevatedButton.styleFrom( backgroundColor: Colors.white10, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), ), ), const SizedBox(width: 10), Expanded( child: ElevatedButton.icon( onPressed: () => _open(facebook), icon: const Icon(Icons.facebook), label: const Text('Facebook'), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF1877F2), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), ), ), ], ), const SizedBox(height: 10), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: () => _open(whatsapp), icon: const Icon(Icons.chat), label: const Text('WhatsApp'), style: OutlinedButton.styleFrom( foregroundColor: Colors.white, side: const BorderSide(color: Colors.white24), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), ), ), ], ), ), ), ); } }
class _InfoCard extends StatelessWidget { final String title; final String text;
const _InfoCard({required this.title, required this.text});
@override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(22), border: Border.all(color: Colors.white12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle(color: Color(0xFFFFA726), fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text(text, style: const TextStyle(height: 1.4)), ], ), ); } }
class _PlayerControls extends StatelessWidget { final AudioHandler handler; const _PlayerControls({required this.handler});
@override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _RoundAction(icon: Icons.play_arrow, label: 'Play', onTap: () => handler.play()), const SizedBox(width: 12), _RoundAction(icon: Icons.pause, label: 'Pause', onTap: () => handler.pause()), const SizedBox(width: 12), _RoundAction(icon: Icons.stop, label: 'Stop', onTap: () => handler.stop()), ], ); } }
class _RoundAction extends StatelessWidget { final IconData icon; final String label; final VoidCallback onTap;
const _RoundAction({ required this.icon, required this.label, required this.onTap, });
@override Widget build(BuildContext context) { return Column( children: [ InkWell( onTap: onTap, borderRadius: BorderRadius.circular(999), child: Container( width: 66, height: 66, decoration: BoxDecoration( color: const Color(0xFFFFA726), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: const Color(0xFFFFA726).withOpacity(0.28), blurRadius: 16, offset: const Offset(0, 6), ), ], ), child: Icon(icon, color: Colors.black, size: 30), ), ), const SizedBox(height: 8), Text(label, style: const TextStyle(color: Colors.white70)), ], ); } }
class RadioHandler extends BaseAudioHandler { final AudioPlayer _player = AudioPlayer(); final String streamUrl = '(https://zeno.fm/radio/fmarenas/)';
RadioHandler() { _init(); }
Future _init() async { try { await _player.setUrl(streamUrl); mediaItem.add( const Media [3:03 p.m., 4/4/2026] humbertoecaceres: import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; import 'package:url_launcher/url_launcher.dart';
void main() async { WidgetsFlutterBinding.ensureInitialized(); final handler = await AudioService.init( builder: () => RadioHandler(), config: const AudioServiceConfig( androidNotificationChannelId: 'com.fmarenas.online.audio', androidNotificationChannelName: 'FM Arenas Online', androidNotificationOngoing: true, androidStopForegroundOnPause: true, ), ); runApp(FmArenasApp(handler: handler)); }
class FmArenasApp extends StatelessWidget { final AudioHandler handler; const FmArenasApp({super.key, required this.handler}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'FM Arenas Online', theme: ThemeData( useMaterial3: true, brightness: Brightness.dark, colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFFFFA726), brightness: Brightness.dark, ), ), home: HomePage(handler: handler), ); } }
class HomePage extends StatelessWidget { final AudioHandler handler; HomePage({super.key, required this.handler});
final Uri website = Uri.parse('https://fmarenas1975.github.io/FM-ARENAS-ONLINE/'); final Uri facebook = Uri.parse('https://www.facebook.com/100092439705105/?locale=es_LA'); final Uri whatsapp = Uri.parse('https://wa.me/54938048058890?text=Hola%20FM%20ArenasBIENVENIDO');
Future _open(Uri url)https://zeno.fm/radio/fmarenas/ async { if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { throw 'No se pudo abrir $url'; } }
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF0F172A), Color(0xFF111827), Color(0xFF1F2937)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: ListView( padding: const EdgeInsets.all(20), children: [ const SizedBox(height: 8), Center( child: Container( width: 110, height: 110, decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(28), ), child: const Icon(Icons.radio, size: 58, color: Color(0xFFFFA726)), ), ), const SizedBox(height: 18), const Center( child: Text( 'FM ARENAS ONLINE', style: TextStyle(fontSize: 28, fontWeight: FontWeight.w800), ), ), const SizedBox(height: 6), const Center( child: Text( 'La Rioja, Argentina', style: TextStyle(color: Colors.white70), ), ), const SizedBox(height: 22), _InfoCard( title: 'En vivo ahora', text: 'Escuchá la radio desde tu celular con una experiencia moderna y simple.', ), const SizedBox(height: 14), _PlayerControls(handler: handler), const SizedBox(height: 14), Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: () => _open(website), icon: const Icon(Icons.language), label: const Text('Sitio web'), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF1877F2), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), ), ), ], ), const SizedBox(height: 10), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: () => _open(whatsapp), icon: const Icon(Icons.chat), label: const Text('WhatsApp'), style: OutlinedButton.styleFrom( foregroundColor: Colors.white, side: const BorderSide(color: Colors.white24), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), ), ), ], ), ), ), ); } }
class _InfoCard extends StatelessWidget { final String title; final String text;
const _InfoCard({required this.title, required this.text});
@override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(22), border: Border.all(color: Colors.white12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle(color: Color(0xFFFFA726), fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text(text, style: const TextStyle(height: 1.4)), ], ), ); } }
class _PlayerControls extends StatelessWidget { final AudioHandler handler; const _PlayerControls({required this.handler});
@override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _RoundAction(icon: Icons.play_arrow, label: 'Play', onTap: () => handler.play()), const SizedBox(width: 12), _RoundAction(icon: Icons.pause, label: 'Pause', onTap: () => handler.pause()), const SizedBox(width: 12), _RoundAction(icon: Icons.stop, label: 'Stop', onTap: () => handler.stop()), ], ); } }
class _RoundAction extends StatelessWidget { final IconData icon; final String label; final VoidCallback onTap;
const _RoundAction({ required this.icon, required this.label, required this.onTap, });
@override Widget build(BuildContext context) { return Column( children: [ InkWell( onTap: onTap, borderRadius: BorderRadius.circular(999), child: Container( width: 66, height: 66, decoration: BoxDecoration( color: const Color(0xFFFFA726), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: const Color(0xFFFFA726).withOpacity(0.28), blurRadius: 16, offset: const Offset(0, 6), ), ], ), child: Icon(icon, color: Colors.black, size: 30), ), ), const SizedBox(height: 8), Text(label, style: const TextStyle(color: Colors.white70)), ], ); } }
class RadioHandler extends BaseAudioHandler { final AudioPlayer _player = AudioPlayer(); final String streamUrl = 'PEGAR_AQUI_LA_URL_REAL_DEL_STREAM';
RadioHandler() { _init(); }
Future _init() async { try { await _player.setUrl(streamUrl); mediaItem.add( const Media